Update of /cvsroot/monetdb/pathfinder/compiler/mil
In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv5403/compiler/mil

Modified Files:
      Tag: M5XQ
        milgen.brg 
Log Message:
propagated changes of Wednesday May 20 2009
from the development trunk to the M5XQ branch

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2009/05/20 - tsheyar: compiler/mil/milgen.brg,1.218
-- Renamed algebra/intro_rec_border.c into algebra/intro_borders.c.
-- Renamed include/intro_rec_border.h into include/intro_borders.h.

-- Extended the physical algebra with a dependent cross product operator
   that only evaluates its right side if the left side produces at least
   one row.

   This change implicitely implements a control structure for some conditionals.
   E.g., the following query conditionally evaluates the independent
   expressions ('doc("xmark-sf0.001.xml")//*' and 'doc("xmark-sf100.xml")//*'):

   if (1 = (1,2,3))
   then doc("xmark-sf0.1.xml")//*
   else doc("xmark-sf100.xml")//*

   With the dependent cross product operator in place this leads to the 
evaluation
   of the (previously independent) then-branch and the avoidance of the 
evaluation
   of the (expensive) else-branch.

-- Adjusted stable output.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


U milgen.brg
Index: milgen.brg
===================================================================
RCS file: /cvsroot/monetdb/pathfinder/compiler/mil/milgen.brg,v
retrieving revision 1.215.2.2
retrieving revision 1.215.2.3
diff -u -d -r1.215.2.2 -r1.215.2.3
--- milgen.brg  7 May 2009 14:46:49 -0000       1.215.2.2
+++ milgen.brg  20 May 2009 16:29:08 -0000      1.215.2.3
@@ -146,7 +146,9 @@
 %term empty_tbl      =   3
 %term attach         =   4
 %term cross          =  10
-%term leftjoin       =  11
+%term dep_cross      =  11
+%term dep_border     =  12
+%term leftjoin       =  13
 %term eqjoin         =  14
 %term semijoin       =  15
 %term thetajoin      =  16
@@ -226,10 +228,12 @@
 Query:    serialize (Side, Rel)                                    =   1 (10);
 Query:    serialize (Side, empty_tbl)                              =   2 (10);
 
-Rel:      lit_tbl                                                  =  10 (10);
-Rel:      empty_tbl                                                =  11 (10);
-Rel:      attach (Rel)                                             =  12 (10);
-Rel:      cross (Rel, Rel)                                         =  13 (10);
+Rel:      lit_tbl                                                  =   8 (10);
+Rel:      empty_tbl                                                =   9 (10);
+Rel:      attach (Rel)                                             =  10 (10);
+Rel:      cross (Rel, Rel)                                         =  11 (10);
+Rel:      dep_cross (Rel, Rel)                                     =  12 (10);
+Rel:      dep_border (Rel)                                         =  13 (10);
 Rel:      leftjoin (Rel, Rel)                                      =  14 (10);
 Rel:      eqjoin (Rel, Rel)                                        =  15 (10);
 Rel:      semijoin (Rel, Rel)                                      =  16 (10);
@@ -1806,6 +1810,53 @@
      }
 } /* fold) */
 
+/**
+ * @brief Translation of the cross product.
+ *
+ * @param p   The physical algebra tree node that we are to translate.
+ *            This function will actually fill @a p's environment
+ *            <code>p->env</code>.
+ */
+static void
+cross_worker (PFpa_op_t *p)
+{ /* fold( */
+    mvar_t *v  = new_var (1);
+    mvar_t *v1 = new_var (1);
+    mvar_t *v2 = new_var (1);
+
+    if (!env_count (L(p)->env) || !env_count (R(p)->env))
+        PFoops (OOPS_FATAL, "Cross does not cope with empty schemas");
+
+    /* The cross product of two relations with cardinality 1
+       requires no MIL code. */
+    if (PFprop_card (L(p)->prop) == 1 &&
+        PFprop_card (R(p)->prop) == 1) {
+        env_copy (p, L(p)->env);
+        env_copy (p, R(p)->env);
+    }
+    else {
+        /* evaluate the cross product and create two map relations */
+        execute (
+            assgn (var (v->name),
+                   cross (
+                       project (ANY_VAR(L(p)->env), nil ()),
+                       reverse (project (ANY_VAR(R(p)->env), nil ())))),
+            assgn (var (v1->name),
+                   reverse (mark (var (v->name), lit_oid (0)))),
+            assgn (var (v2->name),
+                   reverse (mark (reverse (var (v->name)),
+                                  lit_oid (0)))));
+
+        /* map all columns from the left and the right argument */
+        env_map (p, L(p)->env, v1);
+        env_map (p, R(p)->env, v2);
+    }
+
+    unpin (v, 1);
+    unpin (v1, 1);
+    unpin (v2, 1);
+} /* fold) */
+
 #define llscj(p)     llscj_worker ((p), false)
 #define llscj_dup(p) llscj_worker ((p), true)
 /**
@@ -2022,7 +2073,7 @@
 
 } /* fold) */
 
-#ifdef HAVE_PFTIJAH
+#ifdef HAVE_PFTIJAH /* fold( */
 
 /* PFTIJAH helper functions */
 
@@ -2118,7 +2169,7 @@
        }
 }
 
-#endif
+#endif /* fold) */
 
 /***********************************/
 /* fold) end reduce helper functions */
@@ -2576,6 +2627,60 @@
 } /* fold) */
 /* fold) */
 
+/* fold( reduce_dep_border() function implementing the dep_border operator */
+/*
+ * Alternative reducer function. Introduces code that is also used
+ * outside the branch before the conditional part is translated.
+ */
+static void
+reduce_dep_border (PFpa_op_t * p, int goalnt)
+{ /* fold( */
+    int           rule;           /* rule number that matches for this node */
+    short        *nts;            /* target non-terminals for the leaf nodes of
+                                     the current rule */
+    PFpa_op_t    *kids[MAX_KIDS]; /* leaf nodes of this rule */
+
+    assert (p);
+
+    /* determine rule that matches for this non-terminal */
+    rule = PFmilgen_rule (STATE_LABEL (p), goalnt);
+
+    /* guard against too deep recursion */
+    PFrecursion_fence();
+
+    /* PFinfo (OOPS_NOTICE, "match for rule %i", rule); */
+    assert(rule);
+
+    /* initialize the kids[] vector */
+    for (unsigned short i = 0; i < MAX_KIDS; i++)
+        kids[i] = NULL;
+
+    /*
+     * prepare recursive traversal: get information on leaf nodes of
+     * this rule
+     */
+    nts = PFmilgen_nts[rule];
+    PFmilgen_kids (p, rule, kids);
+
+    /* skip the compilation for all operators until we reach
+       the dep_border operator */
+    switch (rule) {
+        /* Rel:      dep_border (Rel) */
+        case 13:
+            if (!p->env) {
+                /* translate sub-DAG starting at the border */
+                reduce (p, goalnt);
+                assert (p->env);
+            }
+            break;
+
+        default:
+            for (unsigned short i = 0; nts[i]; i++)
+                reduce_dep_border (kids[i], nts[i]);
+    }
+} /* fold) */
+/* fold) */
+
 /**
  * @brief Reducer function.
  *
@@ -2624,6 +2729,8 @@
         case 1:
         /* Query:    serialize (Side, empty_tbl) */
         case 2:
+        /* Rel:      dep_cross (Rel, Rel) */
+        case 12:
         /* Rel:      twig (Twig) */
         case 102:
         /* Fcns:     fcns (Twig, Fcns) */
@@ -4138,7 +4245,7 @@
         } break; /* fold) */
 
         /* Rel:      lit_tbl */
-        case 10: /* fold( */
+        case 8: /* fold( */
             /* iterate over table columns */
             for (unsigned int col = 0; col < p->schema.count; col++)
                 for (PFalg_simple_type_t t = 1; t; t <<= 1)
@@ -4169,14 +4276,14 @@
             break; /* fold) */
 
         /* Rel:     empty_tbl */
-        case 11: /* fold( */
+        case 9: /* fold( */
             PFoops (OOPS_FATAL,
                     "empty sequence should never occur in MIL generation."
                     " (optimizations disabled?)");
             break; /* fold) */
 
         /* Rel:      attach (Rel) */
-        case 12: /* fold( */
+        case 10: /* fold( */
             /* copy all the existing variables */
             env_copy (p, L(p)->env);
 
@@ -4212,45 +4319,92 @@
             break; /* fold) */
 
         /* Rel:      cross (Rel, Rel) */
-        case 13: /* fold( */
+        case 11: /* fold( */
+            cross_worker (p);
+            break; /* fold) */
+
+        /* Rel:      dep_cross (Rel, Rel) */
+        case 12: /* fold( */
         {
-            mvar_t *v1 = new_var (1);
-            mvar_t *v2 = new_var (1);
+            PFmil_t *oldmilprog, *then_milprog, *else_milprog;
 
-            v = new_var (1);
-            if (!env_count (L(p)->env) || !env_count (R(p)->env))
-                PFoops (OOPS_FATAL, "Cross does not cope with empty schemas");
+            /* Generate code for left side (and the operators of the right
+               side that are also referenced outside the branch. */
+            execute (comment ("Evaluate left side of dep_cross."));
+            reduce (kids[0], nts[0]);
 
-            /* The cross product of two relations with cardinality 1
-               requires no MIL code. */
-            if (PFprop_card (L(p)->prop) == 1 &&
-                PFprop_card (R(p)->prop) == 1) {
-                env_copy (p, L(p)->env);
-                env_copy (p, R(p)->env);
-            }
-            else {
-                /* evaluate the cross product and create two map relations */
-                execute (
-                    assgn (var (v->name),
-                           cross (
-                               project (ANY_VAR(L(p)->env), nil ()),
-                               reverse (project (ANY_VAR(R(p)->env), nil 
())))),
-                    assgn (var (v1->name),
-                           reverse (mark (var (v->name), lit_oid (0)))),
-                    assgn (var (v2->name),
-                           reverse (mark (reverse (var (v->name)),
-                                          lit_oid (0)))));
+            execute (comment ("Evaluate the portion of the right side of "
+                              "dep_cross that is referenced multiple times."));
+            reduce_dep_border (kids[1], nts[1]);
 
-                /* map all columns from the left and the right argument */
-                env_map (p, L(p)->env, v1);
-                env_map (p, R(p)->env, v2);
+            /* save the current mil program */
+            oldmilprog = milprog;
+
+            /* create a new empty milprog for the then-branch */
+            milprog = nop ();
+
+            /* translate the independent body expression */
+            execute (comment ("Evaluate the independent portion"
+                              " of the right side of dep_cross."));
+            reduce (kids[1], nts[1]);
+
+            /* generate the code for the cross product */
+            execute (comment (" "), comment ("Build the cross product."));
+            cross_worker (p);
+
+            /* store the code for the then-branch */
+            then_milprog = milprog;
+
+            /* create a new empty milprog for the else-branch */
+            milprog = nop ();
+
+            /* For every variable binding the cross product generates
+               we also produce an alternative 'empty. translation. */
+            execute (comment ("Provide the empty result for all BATs."));
+            for (unsigned int col = 0; col < p->schema.count; col++) {
+                PFalg_simple_type_t ty = TYPE_MASK(p->schema.items[col].type);
+                for (PFalg_simple_type_t t = 1; t; t <<= 1) {
+                    if (t & ty) {
+                        /* find the variable name used in the then-branch */
+                        mvar_t *tmp  = env_mvar (p->env,
+                                                 p->schema.items[col].name,
+                                                 t & ty);
+
+                        /* assign an empty BAT to the variable */
+                        execute (
+                            assgn (var (tmp->name),
+                                   seqbase (new (type (mty_void),
+                                                 implty (t, ty)),
+                                            lit_oid (0))));
+                    }
+                }
             }
 
-            unpin (v, 1);
-            unpin (v1, 1);
-            unpin (v2, 1);
+            /* store the code for the else-branch */
+            else_milprog = milprog;
+
+            /* make the old mil program the active one again */
+            milprog = oldmilprog;
+
+            /* Apply the check if the left side of the cross product
+               provides a row. */
+            execute (
+                comment (" "),
+                comment ("Don't evaluate the right side of dep_cross"),
+                comment ("if the left side already provides the empty"),
+                comment ("result."),
+                if_ (gt (count (ANY_VAR (L(p)->env)), lit_int (0)),
+                     then_milprog,
+                     else_milprog));
+
         }   break; /* fold) */
 
+        /* Rel:      dep_border (Rel) */
+        case 13: /* fold( */
+            /* copy the complete environment of the argument */
+            env_copy (p, L(p)->env);
+            break; /* fold) */
+
         /* Rel:      leftjoin (Rel, Rel) */
         case 14:
         /* Rel:      eqjoin (Rel, Rel) */
@@ -5480,7 +5634,7 @@
                                op (VAR (L(p)->env, col1, aat_dec),
                                    VAR (L(p)->env, col2, aat_dec))));
                 }   break; /* fold) */
-                case alg_fun_geo_distance: /* fold( */
+                case alg_fun_geo_distance:
                 case alg_fun_geo_intersection: /* fold( */
                 {
                     PFalg_col_t col1, col2;


------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables 
unlimited royalty-free distribution of the report engine 
for externally facing server and web deployment. 
http://p.sf.net/sfu/businessobjects
_______________________________________________
Monetdb-pf-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/monetdb-pf-checkins

Reply via email to