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

Modified Files:
        intro_rec_border.c physical.c planner.c 
Log Message:
-- Implemented generic function application facility (for the physical algebra).

   Generic functions can now be implemented in the physical algebra using
   the 4 operators pa_fun_call, pa_fun_param, pa_fun_frag_param, and
   pa_frag_extract.  Their semantics is identical to the logical operators
   (see yesterdays checkin message).

-- Added special case for XRPC function calls whose arguments are now
   always sorted by iter, post.

   NOTE: The output order of XRPC function calls is not defined yet.
         If XRPC functions return the results always in a defined order
         the fun_call constructor in physical.c has to be adjusted accordingly.

-- Added function call stub in milgen.brg.

   The implementation of function calls only has to replace the dummy action 
code
   (variable assignments to nil) AND has to enrich the variable environment 
correctly
   (instead of adding dummy variables to it).

   NOTE: The variable environments of the function arguments do not necessarily
         provide all references to BATs that are required by the function 
signature.
         The compilation fills only the BATs for the existing types. This can 
happen
         if the function expects an argument of type item* and the function 
argument
         consists of strings only. The function definition (e.g., the XRPC 
receiver)
         then has to cope with all non-existing BATs.

         The function application operator furthermore needs to fill the 
environment
         for all possible result types. All result BATs therefore have to exist
         (even if they only contains nil values). If the function specifies its
         return type to be item* and the function returns only strings then 
additional
         BATs for integer, double, decimal, untypedAtomic, ... filled with nil 
values
         are also needed.



Index: physical.c
===================================================================
RCS file: /cvsroot/monetdb/pathfinder/compiler/algebra/physical.c,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- physical.c  11 Dec 2007 14:25:55 -0000      1.45
+++ physical.c  14 Dec 2007 12:02:32 -0000      1.46
@@ -3215,6 +3215,27 @@
     return ret;
 }
 
+/**
+ * Constructor for a fragment extract operator
+ * (to be used in combination with a function call)
+ */
+PFpa_op_t *
+PFpa_frag_extract (const PFpa_op_t *n, unsigned int col_pos)
+{
+    PFpa_op_t *ret = wire1 (pa_frag_extract, n);
+
+    /* allocate memory for the result schema */
+    ret->schema.count = 0;
+    ret->schema.items = NULL;
+
+    ret->sem.col_ref.pos = col_pos;
+
+    /* ---- Fragment: costs ---- */
+    ret->cost = 0;
+
+    return ret;
+}
+
 /** Form algebraic disjoint union between two fragments. */
 PFpa_op_t *
 PFpa_frag_union (const PFpa_op_t *n1, const PFpa_op_t *n2)
@@ -3720,6 +3741,113 @@
 }
 
 /**
+ * Constructor for the function application
+ */
+PFpa_op_t *
+PFpa_fun_call (const PFpa_op_t *loop, const PFpa_op_t *param_list,
+               PFalg_schema_t schema, PFalg_fun_call_t kind,
+               PFqname_t qname, void *ctx,
+               PFalg_att_t iter, PFalg_occ_ind_t occ_ind)
+{
+    PFpa_op_t     *ret;
+    unsigned int   i;
+
+    assert (loop);
+    assert (param_list);
+
+    /* create new function application node */
+    ret = wire2 (pa_fun_call, loop, param_list);
+
+    /* allocate memory for the result schema (= schema(n)) */
+    ret->schema.count = schema.count;
+
+    ret->schema.items
+        = PFmalloc (schema.count * sizeof (*(ret->schema.items)));
+
+    for (i = 0; i < schema.count; i++)
+        ret->schema.items[i] = schema.items[i];
+
+    /* insert semantic value */
+    ret->sem.fun_call.kind    = kind;
+    ret->sem.fun_call.qname   = qname;
+    ret->sem.fun_call.ctx     = ctx;
+    ret->sem.fun_call.iter    = iter;
+    ret->sem.fun_call.occ_ind = occ_ind;
+
+    /* by default we don't know anything about the output ordering */
+
+    /* costs */
+    ret->cost = loop->cost + param_list->cost + DEFAULT_COST;
+
+    return ret;
+}
+
+/**
+ * Constructor for a list item of a parameter list
+ * related to function application
+ */
+PFpa_op_t *
+PFpa_fun_param (const PFpa_op_t *argument, const PFpa_op_t *param_list,
+                PFalg_schema_t schema)
+{
+    PFpa_op_t     *ret;
+    unsigned int   i;
+
+    assert (argument);
+    assert (param_list);
+
+    /* create new function application parameter node */
+    ret = wire2 (pa_fun_param, argument, param_list);
+
+    /* allocate memory for the result schema (= schema(n)) */
+    ret->schema.count = schema.count;
+
+    ret->schema.items
+        = PFmalloc (schema.count * sizeof (*(ret->schema.items)));
+
+    for (i = 0; i < schema.count; i++)
+        ret->schema.items[i] = schema.items[i];
+
+    /* ordering stays the same as the input */
+    for (unsigned int i = 0; i < PFord_set_count (argument->orderings); i++)
+        PFord_set_add (ret->orderings, PFord_set_at (argument->orderings, i));
+
+    /* costs */
+    ret->cost = argument->cost + param_list->cost;
+
+    return ret;
+}
+
+/**
+ * Constructor for the fragment information of a list item
+ * of a parameter list related to function application
+ */
+PFpa_op_t *
+PFpa_fun_frag_param (const PFpa_op_t *argument,
+                     const PFpa_op_t *param_list,
+                     unsigned int col_pos)
+{
+    PFpa_op_t     *ret;
+
+    assert (argument);
+    assert (param_list);
+
+    /* create new function application parameter node */
+    ret = wire2 (pa_fun_frag_param, argument, param_list);
+
+    /* allocate memory for the result schema */
+    ret->schema.count = 0;
+    ret->schema.items = NULL;
+
+    ret->sem.col_ref.pos = col_pos;
+    
+    /* costs */
+    ret->cost = argument->cost + param_list->cost;
+
+    return ret;
+}
+
+/**
  * Construct concatenation of multiple strings
  *
  * @a n1 contains the sets of strings @a n2 stores the separator for each set

Index: intro_rec_border.c
===================================================================
RCS file: /cvsroot/monetdb/pathfinder/compiler/algebra/intro_rec_border.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- intro_rec_border.c  29 Oct 2007 20:13:41 -0000      1.6
+++ intro_rec_border.c  14 Dec 2007 12:02:32 -0000      1.7
@@ -95,6 +95,39 @@
                 }
             break;
 
+        case pa_fun_call:
+             base_path = introduce_rec_borders_worker (L(n), bases) ||
+                         introduce_rec_borders_worker (R(n), bases);
+
+             /* the complete function call resides in the recursion */
+             if (base_path) {
+                 /* If one argument of the function call resides in the
+                    recursion the loop relation certainly does as well. */
+
+                 /* Introduce a recursion border for all arguments
+                    that reside outside the recursion. */
+                 PFpa_op_t *param = R(n);
+                 while (param->kind != pa_nil) {
+                     if (param->kind == pa_fun_param && !pfIN(L(param))) {
+                         L(param) = PFpa_rec_border (L(param));
+                         L(param)->prop = L(L(param))->prop;
+                     }
+                     param = R(param);
+                 }
+             }
+             break;
+
+        case pa_fun_param:             
+             /* only collect the base paths */
+             base_path = introduce_rec_borders_worker (L(n), bases) ||
+                         introduce_rec_borders_worker (R(n), bases);
+             break;
+            
+        case pa_fun_frag_param:             
+             /* only collect the base paths */
+             base_path = introduce_rec_borders_worker (R(n), bases);
+             break;
+             
         case pa_fcns:
             /* this also skips the introduction of a rec_border
                operator for the content of an empty elements:

Index: planner.c
===================================================================
RCS file: /cvsroot/monetdb/pathfinder/compiler/algebra/planner.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -d -r1.42 -r1.43
--- planner.c   6 Dec 2007 08:42:15 -0000       1.42
+++ planner.c   14 Dec 2007 12:02:33 -0000      1.43
@@ -124,6 +124,9 @@
  */
 typedef PFpa_op_t plan_t;
 
+/* Function call kind indicator */
+static PFalg_fun_call_t fun_call_kind;
+
 /* ensure some ordering on a given plan */
 static PFplanlist_t *ensure_ordering (const plan_t *unordered,
                                       PFord_ordering_t required);
@@ -1964,6 +1967,23 @@
 }
 
 /**
+ * `frag_extract' operators in the logical algebra just get a 1:1 mapping
+ * into the physical frag_extract operator.
+ */
+static PFplanlist_t *
+plan_frag_extract (const PFla_op_t *n)
+{
+    PFplanlist_t *ret = new_planlist ();
+
+    for (unsigned int i = 0; i < PFarray_last (L(n)->plans); i++)
+        add_plan (ret,
+                  frag_extract (*(plan_t **) PFarray_at (L(n)->plans, i),
+                                n->sem.col_ref.pos));
+
+    return ret;
+}
+
+/**
  * `frag_union' operators in the logical algebra just get a 1:1 mapping
  * into the physical FragUnion operator.
  */
@@ -2091,6 +2111,108 @@
 }
 
 /**
+ * `fun_call' operators in the logical algebra just get a 1:1 mapping
+ * into the physical fun_call operator.
+ */
+static PFplanlist_t *
+plan_fun_call (const PFla_op_t *n)
+{
+    unsigned int i;
+    PFplanlist_t *ret = new_planlist ();
+
+    for (unsigned int i = 0; i < PFarray_last (L(n)->plans); i++)
+        for (unsigned int j = 0; j < PFarray_last (R(n)->plans); j++)
+            add_plan (ret,
+                      fun_call (
+                          *(plan_t **) PFarray_at (L(n)->plans, i),
+                          *(plan_t **) PFarray_at (R(n)->plans, j),
+                          n->schema,
+                          n->sem.fun_call.kind,
+                          n->sem.fun_call.qname,
+                          n->sem.fun_call.ctx,
+                          n->sem.fun_call.iter,
+                          n->sem.fun_call.occ_ind));
+
+    /* check for nodes -- if that's the case we may return
+       only a single plan (as constructors might be involved). */
+    for (i = 0; i < n->schema.count; i++)
+        if (n->schema.items[i].type & aat_node)
+            break;
+    
+    if (i == n->schema.count)
+        return ret;
+    else {
+        PFplanlist_t  *single_plan   = new_planlist ();
+        plan_t        *cheapest_plan = NULL;
+        
+        /* find the cheapest plan */
+        for (unsigned int i = 0; i < PFarray_last (ret); i++)
+            if (!cheapest_plan
+                || costless (*(plan_t **) PFarray_at (ret, i),
+                             cheapest_plan))
+                cheapest_plan = *(plan_t **) PFarray_at (ret, i);
+
+        add_plan (single_plan, cheapest_plan);
+        return single_plan;
+    }
+}
+
+/**
+ * `fun_param' operators in the logical algebra just get a 1:1 mapping
+ * into the physical fun_param operator.
+ */
+static PFplanlist_t *
+plan_fun_param (const PFla_op_t *n)
+{
+    PFplanlist_t *ret = new_planlist (),
+                 *left;
+
+    if (fun_call_kind == alg_fun_call_xrpc) {
+        left = new_planlist ();
+        /* XRPC function call requires its inputs to be properly sorted. */
+        for (unsigned int i = 0; i < PFarray_last (L(n)->plans); i++)
+            add_plans (left,
+                       ensure_ordering (
+                           *(plan_t **) PFarray_at (L(n)->plans, i),
+                           sortby (n->schema.items[0].name,
+                                   n->schema.items[1].name)));
+    }
+    else {
+        left = L(n)->plans;
+    }
+
+    for (unsigned int i = 0; i < PFarray_last (left); i++)
+        for (unsigned int j = 0; j < PFarray_last (R(n)->plans); j++)
+            add_plan (ret,
+                      fun_param (
+                          *(plan_t **) PFarray_at (left, i),
+                          *(plan_t **) PFarray_at (R(n)->plans, j),
+                          n->schema));
+
+    return ret;
+}
+
+/**
+ * `fun_frag_param' operators in the logical algebra just get a 1:1 mapping
+ * into the physical fun_frag_param operator.
+ */
+static PFplanlist_t *
+plan_fun_frag_param (const PFla_op_t *n)
+{
+    PFplanlist_t *ret = new_planlist ();
+
+    for (unsigned int i = 0; i < PFarray_last (L(n)->plans); i++)
+        for (unsigned int j = 0; j < PFarray_last (R(n)->plans); j++)
+            add_plan (ret,
+                      fun_frag_param (
+                          *(plan_t **) PFarray_at (L(n)->plans, i),
+                          *(plan_t **) PFarray_at (R(n)->plans, j),
+                          n->sem.col_ref.pos));
+
+    return ret;
+}
+
+/**
  * Create physical equivalent for the string_join operator
  * (concatenates sets of strings using a seperator for each set)
  *
@@ -2309,10 +2431,8 @@
 
     switch (n->kind)
     {
-        case la_element:
-        case la_attribute:
-        case la_textnode:
-        case la_doc_tbl:
+        case la_twig:
+        case la_fun_call: /* a function call may contain constructors */
             for (i = 0; i < PFLA_OP_MAXCHILD && n->child[i]; i++) {
                 cur_code = clean_up_body_plans_worker (n->child[i], bases);
                 /* collect the codes */
@@ -2590,7 +2710,6 @@
     return true;
 }
 
-
 /**
  * Compute all interesting plans that execute @a n and store them
  * in the @a plans field of @a n.
@@ -2626,6 +2745,8 @@
     switch (n->kind) {
         /* process the following logical algebra nodes top-down */
         case la_rec_fix:
+        case la_fun_call:
+        case la_fun_frag_param:
             break;
         default:
             /* translate bottom-up (ensure that the fragment
@@ -2762,6 +2883,7 @@
 
         case la_roots:          plans = plan_roots (n);        break;
         case la_fragment:       plans = plan_fragment (n);     break;
+        case la_frag_extract:   plans = plan_frag_extract (n); break;
         case la_frag_union:     plans = plan_frag_union (n);   break;
         case la_empty_frag:     plans = plan_empty_frag (n);   break;
 
@@ -2866,6 +2988,28 @@
             add_plan (plans, cheapest_rec_plan);
         } break;
 
+        case la_fun_call:
+        {   /* TOPDOWN */
+            PFalg_fun_call_t old_fun_call_kind = fun_call_kind;
+            fun_call_kind = n->sem.fun_call.kind;
+
+            plan_subexpression (L(n));
+            plan_subexpression (R(n));
+            plans = plan_fun_call (n);
+            
+            fun_call_kind = old_fun_call_kind;
+        } break;
+
+        case la_fun_param:      plans = plan_fun_param (n);    break;  
+        case la_fun_frag_param:
+            /* TOPDOWN */
+            /* change the order of the translation to ensure that fragment
+               information is translated after the value part) */
+            plan_subexpression (R(n));
+            plan_subexpression (L(n));
+            plans = plan_fun_frag_param (n);
+            break;           
+        
         case la_string_join:    plans = plan_string_join (n);  break;
 
         default:
@@ -2888,11 +3032,13 @@
         case la_processi:
         case la_merge_adjacent:
         case la_fragment:
+        case la_frag_extract:
         case la_frag_union:
         case la_empty_frag:
         case la_nil:
         case la_trace_msg:
         case la_trace_map:
+        case la_fun_call:
             break;
 
         default:


-------------------------------------------------------------------------
SF.Net email is sponsored by:
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