Markos Zaharioudakis has proposed merging lp:~zorba-coders/zorba/no-copy into 
lp:zorba.

Commit message:
1. Put back markForSerialization() (renamed as markInUsafeContext())
2. path expr is unsafe if it contains any KindTest with type check and the 
construction mode i strip
3. copying is unsafe only if ns_inherit and ns_preserve


Requested reviews:
  Markos Zaharioudakis (markos-za)

For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/no-copy/+merge/127604

1. Put back markForSerialization() (renamed as markInUsafeContext())
2. path expr is unsafe if it contains any KindTest with type check and the 
construction mode i strip
3. copying is unsafe only if ns_inherit and ns_preserve
-- 
https://code.launchpad.net/~zorba-coders/zorba/no-copy/+merge/127604
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'src/compiler/expression/expr_base.cpp'
--- src/compiler/expression/expr_base.cpp	2012-10-02 11:57:15 +0000
+++ src/compiler/expression/expr_base.cpp	2012-10-02 22:18:11 +0000
@@ -541,6 +541,30 @@
 /*******************************************************************************
 
 ********************************************************************************/
+BoolAnnotationValue expr::getInUnsafeContext() const
+{
+  return (BoolAnnotationValue)
+         ((theFlags1 & IN_UNSAFE_CONTEXT_MASK) >> IN_UNSAFE_CONTEXT);
+}
+
+
+void expr::setInUnsafeContext(BoolAnnotationValue v)
+{
+  theFlags1 &= ~IN_UNSAFE_CONTEXT_MASK;
+  theFlags1 |= (v << IN_UNSAFE_CONTEXT);
+}
+
+
+bool expr::inUnsafeContext() const
+{
+  BoolAnnotationValue v = getInUnsafeContext();
+  return (v == ANNOTATION_TRUE || v == ANNOTATION_TRUE_FIXED);
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
 BoolAnnotationValue expr::getContainsPragma() const
 {
   return (BoolAnnotationValue)

=== modified file 'src/compiler/expression/expr_base.h'
--- src/compiler/expression/expr_base.h	2012-10-02 11:57:15 +0000
+++ src/compiler/expression/expr_base.h	2012-10-02 22:18:11 +0000
@@ -147,8 +147,9 @@
     UNFOLDABLE              = 10,
     CONTAINS_RECURSIVE_CALL = 12,
     PROPAGATES_INPUT_NODES  = 14,
-    MUST_COPY_NODES         = 16,
-    CONTAINS_PRAGMA         = 18
+    IN_UNSAFE_CONTEXT       = 16,
+    MUST_COPY_NODES         = 18,
+    CONTAINS_PRAGMA         = 20
   } Annotationkey;
 
   typedef enum
@@ -161,8 +162,9 @@
     UNFOLDABLE_MASK               = 0xC00,
     CONTAINS_RECURSIVE_CALL_MASK  = 0x3000,
     PROPAGATES_INPUT_NODES_MASK   = 0xC000,
-    MUST_COPY_NODES_MASK          = 0x30000,
-    CONTAINS_PRAGMA_MASK          = 0xC0000
+    IN_UNSAFE_CONTEXT_MASK        = 0x30000,
+    MUST_COPY_NODES_MASK          = 0xC0000,
+    CONTAINS_PRAGMA_MASK          = 0x300000
   } AnnotationMask;
 
 
@@ -313,6 +315,13 @@
 
   void setMustCopyNodes(BoolAnnotationValue v);
 
+  // Annotation : inUnsafeContext
+  BoolAnnotationValue getInUnsafeContext() const;
+
+  void setInUnsafeContext(BoolAnnotationValue v);
+
+  bool inUnsafeContext() const;
+
   // Annotation : containsPragma
   BoolAnnotationValue getContainsPragma() const;
 

=== modified file 'src/compiler/rewriter/rules/nodeid_rules.cpp'
--- src/compiler/rewriter/rules/nodeid_rules.cpp	2012-10-02 11:57:15 +0000
+++ src/compiler/rewriter/rules/nodeid_rules.cpp	2012-10-02 22:18:11 +0000
@@ -600,11 +600,11 @@
           // inherited from the referencing tree if N had been copied into that
           // tree. (On the other hand it is ok if the query result contains nodes
           // which are not shared but have shared descendants). To handle this,
-          // we set theIsInUnsafeContext so that any exprs that (a) extract nodes
+          // we call markInUnsafeContext() so that any exprs that (a) extract nodes
           // out of input nodes and (b) may propagate the extracted nodes to the
           // query result will be considered as unsafe and thus require that 
           // their input trees are standalone.
-          theIsInUnsafeContext = true;
+          markInUnsafeContext(node);
         }
       }
       else
@@ -652,25 +652,11 @@
     expr* node,
     UDFCallChain& udfCaller)
 {
-  TypeManager* tm = node->get_type_manager();
-  RootTypeManager& rtm = GENV_TYPESYSTEM;
-
-  bool savedIsInUnsafeContext = theIsInUnsafeContext;
-
-  if (theIsInUnsafeContext)
-  {
-    xqtref_t retType = node->get_return_type();
-
-    if (TypeOps::is_subtype(tm, *retType, *rtm.ANY_ATOMIC_TYPE_STAR))
-      theIsInUnsafeContext = false;
-  }
-
   switch (node->get_expr_kind())
   {
   case const_expr_kind:
   case var_expr_kind:
   {
-    theIsInUnsafeContext = savedIsInUnsafeContext;
     return;
   }
 
@@ -692,7 +678,8 @@
 
     static_context* sctx = e->get_sctx();
 
-    if (sctx->preserve_mode() != StaticContextConsts::no_preserve_ns)
+    if (sctx->preserve_mode() == StaticContextConsts::preserve_ns &&
+        sctx->inherit_mode() == StaticContextConsts::inherit_ns)
     {
       csize numPairs = e->num_pairs();
       for (csize i = 0; i < numPairs; ++i)
@@ -717,7 +704,8 @@
 
     static_context* sctx = e->get_sctx();
 
-    if (sctx->preserve_mode() != StaticContextConsts::no_preserve_ns)
+    if (sctx->preserve_mode() == StaticContextConsts::preserve_ns &&
+        sctx->inherit_mode() == StaticContextConsts::inherit_ns)
     {
       std::vector<expr*> sources;
       theSourceFinder->findNodeSources(e->get_expr(), &udfCaller, sources);
@@ -732,7 +720,7 @@
   {
     relpath_expr* e = static_cast<relpath_expr *>(node);
 
-    if (theIsInUnsafeContext)
+    if (e->inUnsafeContext())
     {
       std::vector<expr*> sources;
       theSourceFinder->findNodeSources((*e)[0],  &udfCaller, sources);
@@ -750,6 +738,7 @@
 
         if (axisKind != axis_kind_child &&
             axisKind != axis_kind_descendant &&
+            axisKind != axis_kind_descendant_or_self &&
             axisKind != axis_kind_self &&
             axisKind != axis_kind_attribute)
         {
@@ -758,12 +747,24 @@
           markSources(sources);
           break;
         }
+        else
+        {
+          match_expr* matchExpr = axisExpr->getTest();
+
+          if (matchExpr->getTypeName() != NULL &&
+              node->get_sctx()->construction_mode() == StaticContextConsts::cons_strip)
+          {
+            std::vector<expr*> sources;
+            theSourceFinder->findNodeSources((*e)[0],  &udfCaller, sources);
+            markSources(sources);
+            break;
+          }
+        }
       }
     }
 
     applyInternal(rCtx, (*e)[0], udfCaller);
 
-    theIsInUnsafeContext = savedIsInUnsafeContext;
     return;
   }
 
@@ -846,7 +847,7 @@
   {
     if (node->get_sctx()->construction_mode() == StaticContextConsts::cons_strip)
     {
-      theIsInUnsafeContext = true;
+      markInUnsafeContext(node);
     }
 
     break;
@@ -895,7 +896,8 @@
 
     static_context* sctx = e->get_sctx();
 
-    if (sctx->preserve_mode() != StaticContextConsts::no_preserve_ns)
+    if (sctx->preserve_mode() == StaticContextConsts::preserve_ns &&
+        sctx->inherit_mode() == StaticContextConsts::inherit_ns)
     {
       std::vector<copy_clause*>::const_iterator ite = e->begin();
       std::vector<copy_clause*>::const_iterator end = e->end();
@@ -1028,7 +1030,6 @@
 
     applyInternal(rCtx, udf->getBody(), dummyUdfCaller);
 
-    theIsInUnsafeContext = savedIsInUnsafeContext;
     return;
   }
 
@@ -1049,9 +1050,6 @@
     iter.next();
   }
 
-
-  theIsInUnsafeContext = savedIsInUnsafeContext;
-
   return;
 }
 
@@ -1090,5 +1088,315 @@
 }
 
 
+/*******************************************************************************
+  This method is called when an expr E1 satisfies a condition that may make a
+  sub-expr E2 of E1 be unsafe, even though E2 by itself is safe. 
+
+  This method marks as being in "unsafe context" any expr that may produce
+  nodes which may be propagated into the result of E1.
+********************************************************************************/
+void MarkNodeCopyProps::markInUnsafeContext(expr* node)
+{
+  TypeManager* tm = node->get_type_manager();
+  RootTypeManager& rtm = GENV_TYPESYSTEM;
+
+  xqtref_t retType = node->get_return_type();
+
+  if (TypeOps::is_subtype(tm, *retType, *rtm.ANY_ATOMIC_TYPE_STAR))
+    return;
+
+  switch (node->get_expr_kind())
+  {
+  case const_expr_kind:
+  {
+    return;
+  }
+  case var_expr_kind:
+  {
+    var_expr* e = static_cast<var_expr*>(node);
+
+    switch (e->get_kind())
+    {
+    case var_expr::for_var:
+    case var_expr::let_var:
+    case var_expr::win_var:
+    case var_expr::wincond_out_var:
+    case var_expr::wincond_in_var:
+    case var_expr::non_groupby_var:
+    {
+      if (!e->inUnsafeContext())
+      {
+        e->setInUnsafeContext(ANNOTATION_TRUE);
+        markInUnsafeContext(e->get_domain_expr());
+      }
+      return;
+    }
+
+    case var_expr::copy_var:
+    case var_expr::catch_var:
+    {
+      e->setInUnsafeContext(ANNOTATION_TRUE);
+      return;
+    }
+
+    case var_expr::arg_var:
+    {
+      e->setInUnsafeContext(ANNOTATION_TRUE);
+      return;
+    }
+
+    case var_expr::prolog_var:
+    case var_expr::local_var:
+    {
+      if (!e->inUnsafeContext())
+      {
+        e->setInUnsafeContext(ANNOTATION_TRUE);
+
+        std::vector<expr*>::const_iterator ite = e->setExprsBegin();
+        std::vector<expr*>::const_iterator end = e->setExprsEnd();
+
+        for (; ite != end; ++ite)
+        {
+          expr* setExpr = *ite;
+
+          if (setExpr->get_expr_kind() == var_decl_expr_kind)
+          {
+            markInUnsafeContext(static_cast<var_decl_expr*>(setExpr)->get_init_expr());
+          }
+          else
+          {
+            assert(setExpr->get_expr_kind() == var_set_expr_kind);
+
+            markInUnsafeContext(static_cast<var_set_expr*>(setExpr)->get_expr());
+          }
+        }
+      }
+      return;
+    }
+
+    case var_expr::groupby_var:
+    case var_expr::wincond_in_pos_var:
+    case var_expr::wincond_out_pos_var:
+    case var_expr::pos_var:
+    case var_expr::score_var:
+    case var_expr::count_var:
+    default:
+    {
+      ZORBA_ASSERT(false);
+      return;
+    }
+    }
+  }
+
+  case doc_expr_kind:
+  case elem_expr_kind:
+  case attr_expr_kind:
+  case text_expr_kind:
+  case pi_expr_kind:
+  {
+    break;
+  }
+
+#ifdef ZORBA_WITH_JSON
+  case json_object_expr_kind:
+  case json_direct_object_expr_kind:
+  case json_array_expr_kind:
+  {
+    break;
+  }
+#endif
+
+  case relpath_expr_kind:
+  {
+    relpath_expr* e = static_cast<relpath_expr *>(node);
+    e->setInUnsafeContext(ANNOTATION_TRUE);
+    markInUnsafeContext((*e)[0]);
+    return;
+  }
+
+  case gflwor_expr_kind:
+  case flwor_expr_kind:
+  {
+    flwor_expr* e = static_cast<flwor_expr *>(node);
+    e->setInUnsafeContext(ANNOTATION_TRUE);
+    markInUnsafeContext(e->get_return_expr());
+    return;
+  }
+
+  case if_expr_kind:
+  case trycatch_expr_kind:
+  {
+    break;
+  }
+
+  case fo_expr_kind:
+  {
+    fo_expr* e = static_cast<fo_expr *>(node);
+    function* f = e->get_func();
+
+    e->setInUnsafeContext(ANNOTATION_TRUE);
+
+    if (f->isUdf() && static_cast<user_function*>(f)->getBody() != NULL)
+    {
+      user_function* udf = static_cast<user_function*>(f);
+      expr* body = udf->getBody();
+
+      if (!body->inUnsafeContext())
+      {
+        markInUnsafeContext(body);
+      }
+
+      std::vector<var_expr*>::const_iterator ite = udf->getArgVars().begin();
+      std::vector<var_expr*>::const_iterator end = udf->getArgVars().end();
+      for (; ite != end; ++ite)
+      {
+        expr* argVar = (*ite);
+        if (argVar->inUnsafeContext())
+        {
+          expr* argExpr = e->get_arg(ite - udf->getArgVars().begin());
+          markInUnsafeContext(argExpr);
+        }
+      }
+    } // f->isUdf()
+    else
+    {
+      csize numArgs = e->num_args();
+      for (csize i = 0; i < numArgs; ++i)
+      {
+        if (f->propagatesInputNodes(e, i))
+        {
+          markInUnsafeContext(e->get_arg(i));
+        }
+      }
+    }
+
+    return;
+  }
+
+  case treat_expr_kind:
+  case order_expr_kind:
+  case wrapper_expr_kind:
+  case function_trace_expr_kind:
+  case extension_expr_kind:
+  {
+    break;
+  }
+
+  case validate_expr_kind:
+  {
+    node->setInUnsafeContext(ANNOTATION_TRUE);
+    return;
+  }
+
+  case transform_expr_kind:
+  {
+    transform_expr* e = static_cast<transform_expr *>(node);
+    e->setInUnsafeContext(ANNOTATION_TRUE);
+    markInUnsafeContext(e->getReturnExpr());
+    return;
+  }
+
+  case block_expr_kind:
+  {
+    block_expr* e = static_cast<block_expr *>(node);
+    e->setInUnsafeContext(ANNOTATION_TRUE);
+    expr* lastChild = (*e)[e->size()-1];
+    markInUnsafeContext(lastChild);
+    return;
+  }
+
+  case var_decl_expr_kind:
+  case var_set_expr_kind:
+  {
+    return;
+  }
+
+  case apply_expr_kind:
+  {
+    break;
+  }
+
+  case exit_catcher_expr_kind:
+  {
+    exit_catcher_expr* e = static_cast<exit_catcher_expr*>(node);
+
+    std::vector<expr*>::const_iterator ite = e->exitExprsBegin();
+    std::vector<expr*>::const_iterator end = e->exitExprsEnd();
+
+    for (; ite != end; ++ite)
+    {
+      exit_expr* ex = static_cast<exit_expr*>(*ite);
+
+      markInUnsafeContext(ex->get_expr());
+    }
+
+    break;
+  }
+
+
+  case eval_expr_kind:
+  {
+    break;
+  }
+
+  case debugger_expr_kind:
+  {
+    break;  // ????
+  }
+
+  case dynamic_function_invocation_expr_kind:
+  {
+    break;
+  }
+
+  case function_item_expr_kind:
+  {
+    function_item_expr* e = static_cast<function_item_expr*>(node);
+
+    user_function* udf = static_cast<user_function*>(e->get_function());
+
+    markInUnsafeContext(udf->getBody());
+
+    return;
+  }
+
+  case promote_expr_kind:
+  case castable_expr_kind:
+  case cast_expr_kind:
+  case instanceof_expr_kind:
+  case name_cast_expr_kind:
+  case axis_step_expr_kind:
+  case match_expr_kind:
+  case delete_expr_kind:
+  case rename_expr_kind:
+  case insert_expr_kind:
+  case replace_expr_kind:
+  case while_expr_kind:
+  case flowctl_expr_kind:
+  case exit_expr_kind:
+#ifndef ZORBA_NO_FULL_TEXT
+  case ft_expr_kind:
+#endif
+  default:
+    ZORBA_ASSERT(false);
+  }
+
+  node->setInUnsafeContext(ANNOTATION_TRUE);
+
+  ExprIterator iter(node);
+  while(!iter.done())
+  {
+    expr* child = (**iter);
+    if (child != NULL)
+    {
+      markInUnsafeContext(child);
+    }
+    iter.next();
+  }
+
+  return;
+}
+
+
 }
 /* vim:set et sw=2 ts=2: */

=== modified file 'src/compiler/rewriter/rules/ruleset.h'
--- src/compiler/rewriter/rules/ruleset.h	2012-10-02 11:57:15 +0000
+++ src/compiler/rewriter/rules/ruleset.h	2012-10-02 22:18:11 +0000
@@ -125,11 +125,6 @@
 
 /*******************************************************************************
 
-  theIsInUnsafeContext:
-  ---------------------
-  If true, it indicates that an expr E1 satisfies a condition that makes a
-  sub-expr E2 of E1 be unsafe, even though E2 by itself is safe.
-
 ********************************************************************************/
 class MarkNodeCopyProps : public RewriteRule
 {
@@ -140,13 +135,10 @@
 
   UdfCalls         theProcessedUDFCalls;
 
-  bool             theIsInUnsafeContext;
-
 public:
   MarkNodeCopyProps()
     :
-    RewriteRule(RewriteRule::MarkNodeCopyProps, "MarkNodeCopyProps"),
-    theIsInUnsafeContext(false)
+    RewriteRule(RewriteRule::MarkNodeCopyProps, "MarkNodeCopyProps")
   {
   }
 
@@ -156,6 +148,8 @@
   void applyInternal(RewriterContext& rCtx, expr* node, UDFCallChain& udfCaller);
 
   void markSources(const std::vector<expr*>& sources);
+
+  void markInUnsafeContext(expr* node);
 };
 
 

=== added file 'test/rbkt/ExpQueryResults/zorba/no-copy/test4.xml.res'
--- test/rbkt/ExpQueryResults/zorba/no-copy/test4.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/no-copy/test4.xml.res	2012-10-02 22:18:11 +0000
@@ -0,0 +1,1 @@
+<s:name xmlns:s="http://www.zorba-xquery.org/simple";>foo</s:name>

=== added file 'test/rbkt/ExpQueryResults/zorba/no-copy/test5.xml.res'
--- test/rbkt/ExpQueryResults/zorba/no-copy/test5.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/no-copy/test5.xml.res	2012-10-02 22:18:11 +0000
@@ -0,0 +1,1 @@
+<s:name xmlns:s="http://www.zorba-xquery.org/simple";>foo</s:name>    true

=== added file 'test/rbkt/Queries/zorba/no-copy/test4.xq'
--- test/rbkt/Queries/zorba/no-copy/test4.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/no-copy/test4.xq	2012-10-02 22:18:11 +0000
@@ -0,0 +1,17 @@
+
+declare namespace opt = "http://www.zorba-xquery.com/options/optimizer";;
+
+declare construction strip;
+
+declare copy-namespaces preserve, no-inherit;
+
+
+import schema namespace s="http://www.zorba-xquery.org/simple"; at "simple.xsd";
+
+declare option opt:enable "for-serialization-only";
+
+declare variable $doc := <s:person><s:name>foo</s:name><s:age>25</s:age></s:person>;
+
+let $vdoc := validate { $doc }
+let $copy := <root>{$vdoc/s:name}</root>
+return $copy/child::element(*, xs:untyped)

=== added file 'test/rbkt/Queries/zorba/no-copy/test5.xq'
--- test/rbkt/Queries/zorba/no-copy/test5.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/no-copy/test5.xq	2012-10-02 22:18:11 +0000
@@ -0,0 +1,16 @@
+declare namespace opt = "http://www.zorba-xquery.com/options/optimizer";;
+
+declare construction strip;
+
+declare copy-namespaces preserve, no-inherit;
+
+import schema namespace s="http://www.zorba-xquery.org/simple"; at "simple.xsd";
+
+declare option opt:enable "for-serialization-only";
+
+declare variable $doc := <s:person><s:name>foo</s:name><s:age>25</s:age></s:person>;
+
+let $vdoc := validate { $doc }
+let $copy := <root>{$vdoc/s:name}</root>
+let $copyname := $copy/s:name
+return ($copyname, "   ", $copyname instance of element(*, xs:string))

-- 
Mailing list: https://launchpad.net/~zorba-coders
Post to     : zorba-coders@lists.launchpad.net
Unsubscribe : https://launchpad.net/~zorba-coders
More help   : https://help.launchpad.net/ListHelp

Reply via email to