Merge lp:~zorba-coders/zorba/no-copy into lp:zorba

Proposed by Markos Zaharioudakis
Status: Merged
Approved by: Markos Zaharioudakis
Approved revision: 11077
Merged at revision: 11084
Proposed branch: lp:~zorba-coders/zorba/no-copy
Merge into: lp:zorba
Diff against target: 633 lines (+411/-39)
8 files modified
src/compiler/expression/expr_base.cpp (+24/-0)
src/compiler/expression/expr_base.h (+13/-4)
src/compiler/rewriter/rules/nodeid_rules.cpp (+336/-26)
src/compiler/rewriter/rules/ruleset.h (+3/-9)
test/rbkt/ExpQueryResults/zorba/no-copy/test4.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/no-copy/test5.xml.res (+1/-0)
test/rbkt/Queries/zorba/no-copy/test4.xq (+17/-0)
test/rbkt/Queries/zorba/no-copy/test5.xq (+16/-0)
To merge this branch: bzr merge lp:~zorba-coders/zorba/no-copy
Reviewer Review Type Date Requested Status
Markos Zaharioudakis Approve
Review via email: mp+127604@code.launchpad.net

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

Description of the change

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

To post a comment you must log in.
lp:~zorba-coders/zorba/no-copy updated
11077. By Markos Zaharioudakis

put back markForSerialization() + path expr is unsafe if it contains any KindTest with type and the construction mode i strip + copying is unsafe only if ns_inherit and ns_preserve

Revision history for this message
Markos Zaharioudakis (markos-za) :
review: Approve
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job no-copy-2012-10-02T22-59-53.733Z is finished. The final status was:

All tests succeeded!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/compiler/expression/expr_base.cpp'
2--- src/compiler/expression/expr_base.cpp 2012-10-02 11:57:15 +0000
3+++ src/compiler/expression/expr_base.cpp 2012-10-02 22:52:19 +0000
4@@ -541,6 +541,30 @@
5 /*******************************************************************************
6
7 ********************************************************************************/
8+BoolAnnotationValue expr::getInUnsafeContext() const
9+{
10+ return (BoolAnnotationValue)
11+ ((theFlags1 & IN_UNSAFE_CONTEXT_MASK) >> IN_UNSAFE_CONTEXT);
12+}
13+
14+
15+void expr::setInUnsafeContext(BoolAnnotationValue v)
16+{
17+ theFlags1 &= ~IN_UNSAFE_CONTEXT_MASK;
18+ theFlags1 |= (v << IN_UNSAFE_CONTEXT);
19+}
20+
21+
22+bool expr::inUnsafeContext() const
23+{
24+ BoolAnnotationValue v = getInUnsafeContext();
25+ return (v == ANNOTATION_TRUE || v == ANNOTATION_TRUE_FIXED);
26+}
27+
28+
29+/*******************************************************************************
30+
31+********************************************************************************/
32 BoolAnnotationValue expr::getContainsPragma() const
33 {
34 return (BoolAnnotationValue)
35
36=== modified file 'src/compiler/expression/expr_base.h'
37--- src/compiler/expression/expr_base.h 2012-10-02 11:57:15 +0000
38+++ src/compiler/expression/expr_base.h 2012-10-02 22:52:19 +0000
39@@ -147,8 +147,9 @@
40 UNFOLDABLE = 10,
41 CONTAINS_RECURSIVE_CALL = 12,
42 PROPAGATES_INPUT_NODES = 14,
43- MUST_COPY_NODES = 16,
44- CONTAINS_PRAGMA = 18
45+ IN_UNSAFE_CONTEXT = 16,
46+ MUST_COPY_NODES = 18,
47+ CONTAINS_PRAGMA = 20
48 } Annotationkey;
49
50 typedef enum
51@@ -161,8 +162,9 @@
52 UNFOLDABLE_MASK = 0xC00,
53 CONTAINS_RECURSIVE_CALL_MASK = 0x3000,
54 PROPAGATES_INPUT_NODES_MASK = 0xC000,
55- MUST_COPY_NODES_MASK = 0x30000,
56- CONTAINS_PRAGMA_MASK = 0xC0000
57+ IN_UNSAFE_CONTEXT_MASK = 0x30000,
58+ MUST_COPY_NODES_MASK = 0xC0000,
59+ CONTAINS_PRAGMA_MASK = 0x300000
60 } AnnotationMask;
61
62
63@@ -313,6 +315,13 @@
64
65 void setMustCopyNodes(BoolAnnotationValue v);
66
67+ // Annotation : inUnsafeContext
68+ BoolAnnotationValue getInUnsafeContext() const;
69+
70+ void setInUnsafeContext(BoolAnnotationValue v);
71+
72+ bool inUnsafeContext() const;
73+
74 // Annotation : containsPragma
75 BoolAnnotationValue getContainsPragma() const;
76
77
78=== modified file 'src/compiler/rewriter/rules/nodeid_rules.cpp'
79--- src/compiler/rewriter/rules/nodeid_rules.cpp 2012-10-02 11:57:15 +0000
80+++ src/compiler/rewriter/rules/nodeid_rules.cpp 2012-10-02 22:52:19 +0000
81@@ -600,11 +600,11 @@
82 // inherited from the referencing tree if N had been copied into that
83 // tree. (On the other hand it is ok if the query result contains nodes
84 // which are not shared but have shared descendants). To handle this,
85- // we set theIsInUnsafeContext so that any exprs that (a) extract nodes
86+ // we call markInUnsafeContext() so that any exprs that (a) extract nodes
87 // out of input nodes and (b) may propagate the extracted nodes to the
88 // query result will be considered as unsafe and thus require that
89 // their input trees are standalone.
90- theIsInUnsafeContext = true;
91+ markInUnsafeContext(node);
92 }
93 }
94 else
95@@ -652,25 +652,11 @@
96 expr* node,
97 UDFCallChain& udfCaller)
98 {
99- TypeManager* tm = node->get_type_manager();
100- RootTypeManager& rtm = GENV_TYPESYSTEM;
101-
102- bool savedIsInUnsafeContext = theIsInUnsafeContext;
103-
104- if (theIsInUnsafeContext)
105- {
106- xqtref_t retType = node->get_return_type();
107-
108- if (TypeOps::is_subtype(tm, *retType, *rtm.ANY_ATOMIC_TYPE_STAR))
109- theIsInUnsafeContext = false;
110- }
111-
112 switch (node->get_expr_kind())
113 {
114 case const_expr_kind:
115 case var_expr_kind:
116 {
117- theIsInUnsafeContext = savedIsInUnsafeContext;
118 return;
119 }
120
121@@ -692,7 +678,8 @@
122
123 static_context* sctx = e->get_sctx();
124
125- if (sctx->preserve_mode() != StaticContextConsts::no_preserve_ns)
126+ if (sctx->preserve_mode() == StaticContextConsts::preserve_ns &&
127+ sctx->inherit_mode() == StaticContextConsts::inherit_ns)
128 {
129 csize numPairs = e->num_pairs();
130 for (csize i = 0; i < numPairs; ++i)
131@@ -717,7 +704,8 @@
132
133 static_context* sctx = e->get_sctx();
134
135- if (sctx->preserve_mode() != StaticContextConsts::no_preserve_ns)
136+ if (sctx->preserve_mode() == StaticContextConsts::preserve_ns &&
137+ sctx->inherit_mode() == StaticContextConsts::inherit_ns)
138 {
139 std::vector<expr*> sources;
140 theSourceFinder->findNodeSources(e->get_expr(), &udfCaller, sources);
141@@ -732,7 +720,7 @@
142 {
143 relpath_expr* e = static_cast<relpath_expr *>(node);
144
145- if (theIsInUnsafeContext)
146+ if (e->inUnsafeContext())
147 {
148 std::vector<expr*> sources;
149 theSourceFinder->findNodeSources((*e)[0], &udfCaller, sources);
150@@ -750,6 +738,7 @@
151
152 if (axisKind != axis_kind_child &&
153 axisKind != axis_kind_descendant &&
154+ axisKind != axis_kind_descendant_or_self &&
155 axisKind != axis_kind_self &&
156 axisKind != axis_kind_attribute)
157 {
158@@ -758,12 +747,24 @@
159 markSources(sources);
160 break;
161 }
162+ else
163+ {
164+ match_expr* matchExpr = axisExpr->getTest();
165+
166+ if (matchExpr->getTypeName() != NULL &&
167+ node->get_sctx()->construction_mode() == StaticContextConsts::cons_strip)
168+ {
169+ std::vector<expr*> sources;
170+ theSourceFinder->findNodeSources((*e)[0], &udfCaller, sources);
171+ markSources(sources);
172+ break;
173+ }
174+ }
175 }
176 }
177
178 applyInternal(rCtx, (*e)[0], udfCaller);
179
180- theIsInUnsafeContext = savedIsInUnsafeContext;
181 return;
182 }
183
184@@ -846,7 +847,9 @@
185 {
186 if (node->get_sctx()->construction_mode() == StaticContextConsts::cons_strip)
187 {
188- theIsInUnsafeContext = true;
189+ cast_or_castable_base_expr* e = static_cast<cast_or_castable_base_expr*>(node);
190+
191+ markInUnsafeContext(e->get_input());
192 }
193
194 break;
195@@ -895,7 +898,8 @@
196
197 static_context* sctx = e->get_sctx();
198
199- if (sctx->preserve_mode() != StaticContextConsts::no_preserve_ns)
200+ if (sctx->preserve_mode() == StaticContextConsts::preserve_ns &&
201+ sctx->inherit_mode() == StaticContextConsts::inherit_ns)
202 {
203 std::vector<copy_clause*>::const_iterator ite = e->begin();
204 std::vector<copy_clause*>::const_iterator end = e->end();
205@@ -1028,7 +1032,6 @@
206
207 applyInternal(rCtx, udf->getBody(), dummyUdfCaller);
208
209- theIsInUnsafeContext = savedIsInUnsafeContext;
210 return;
211 }
212
213@@ -1049,9 +1052,6 @@
214 iter.next();
215 }
216
217-
218- theIsInUnsafeContext = savedIsInUnsafeContext;
219-
220 return;
221 }
222
223@@ -1090,5 +1090,315 @@
224 }
225
226
227+/*******************************************************************************
228+ This method is called when an expr E1 satisfies a condition that may make a
229+ sub-expr E2 of E1 be unsafe, even though E2 by itself is safe.
230+
231+ This method marks as being in "unsafe context" any expr that may produce
232+ nodes which may be propagated into the result of E1.
233+********************************************************************************/
234+void MarkNodeCopyProps::markInUnsafeContext(expr* node)
235+{
236+ TypeManager* tm = node->get_type_manager();
237+ RootTypeManager& rtm = GENV_TYPESYSTEM;
238+
239+ xqtref_t retType = node->get_return_type();
240+
241+ if (TypeOps::is_subtype(tm, *retType, *rtm.ANY_ATOMIC_TYPE_STAR))
242+ return;
243+
244+ switch (node->get_expr_kind())
245+ {
246+ case const_expr_kind:
247+ {
248+ return;
249+ }
250+ case var_expr_kind:
251+ {
252+ var_expr* e = static_cast<var_expr*>(node);
253+
254+ switch (e->get_kind())
255+ {
256+ case var_expr::for_var:
257+ case var_expr::let_var:
258+ case var_expr::win_var:
259+ case var_expr::wincond_out_var:
260+ case var_expr::wincond_in_var:
261+ case var_expr::non_groupby_var:
262+ {
263+ if (!e->inUnsafeContext())
264+ {
265+ e->setInUnsafeContext(ANNOTATION_TRUE);
266+ markInUnsafeContext(e->get_domain_expr());
267+ }
268+ return;
269+ }
270+
271+ case var_expr::copy_var:
272+ case var_expr::catch_var:
273+ {
274+ e->setInUnsafeContext(ANNOTATION_TRUE);
275+ return;
276+ }
277+
278+ case var_expr::arg_var:
279+ {
280+ e->setInUnsafeContext(ANNOTATION_TRUE);
281+ return;
282+ }
283+
284+ case var_expr::prolog_var:
285+ case var_expr::local_var:
286+ {
287+ if (!e->inUnsafeContext())
288+ {
289+ e->setInUnsafeContext(ANNOTATION_TRUE);
290+
291+ std::vector<expr*>::const_iterator ite = e->setExprsBegin();
292+ std::vector<expr*>::const_iterator end = e->setExprsEnd();
293+
294+ for (; ite != end; ++ite)
295+ {
296+ expr* setExpr = *ite;
297+
298+ if (setExpr->get_expr_kind() == var_decl_expr_kind)
299+ {
300+ markInUnsafeContext(static_cast<var_decl_expr*>(setExpr)->get_init_expr());
301+ }
302+ else
303+ {
304+ assert(setExpr->get_expr_kind() == var_set_expr_kind);
305+
306+ markInUnsafeContext(static_cast<var_set_expr*>(setExpr)->get_expr());
307+ }
308+ }
309+ }
310+ return;
311+ }
312+
313+ case var_expr::groupby_var:
314+ case var_expr::wincond_in_pos_var:
315+ case var_expr::wincond_out_pos_var:
316+ case var_expr::pos_var:
317+ case var_expr::score_var:
318+ case var_expr::count_var:
319+ default:
320+ {
321+ ZORBA_ASSERT(false);
322+ return;
323+ }
324+ }
325+ }
326+
327+ case doc_expr_kind:
328+ case elem_expr_kind:
329+ case attr_expr_kind:
330+ case text_expr_kind:
331+ case pi_expr_kind:
332+ {
333+ break;
334+ }
335+
336+#ifdef ZORBA_WITH_JSON
337+ case json_object_expr_kind:
338+ case json_direct_object_expr_kind:
339+ case json_array_expr_kind:
340+ {
341+ break;
342+ }
343+#endif
344+
345+ case relpath_expr_kind:
346+ {
347+ relpath_expr* e = static_cast<relpath_expr *>(node);
348+ e->setInUnsafeContext(ANNOTATION_TRUE);
349+ markInUnsafeContext((*e)[0]);
350+ return;
351+ }
352+
353+ case gflwor_expr_kind:
354+ case flwor_expr_kind:
355+ {
356+ flwor_expr* e = static_cast<flwor_expr *>(node);
357+ e->setInUnsafeContext(ANNOTATION_TRUE);
358+ markInUnsafeContext(e->get_return_expr());
359+ return;
360+ }
361+
362+ case if_expr_kind:
363+ case trycatch_expr_kind:
364+ {
365+ break;
366+ }
367+
368+ case fo_expr_kind:
369+ {
370+ fo_expr* e = static_cast<fo_expr *>(node);
371+ function* f = e->get_func();
372+
373+ e->setInUnsafeContext(ANNOTATION_TRUE);
374+
375+ if (f->isUdf() && static_cast<user_function*>(f)->getBody() != NULL)
376+ {
377+ user_function* udf = static_cast<user_function*>(f);
378+ expr* body = udf->getBody();
379+
380+ if (!body->inUnsafeContext())
381+ {
382+ markInUnsafeContext(body);
383+ }
384+
385+ std::vector<var_expr*>::const_iterator ite = udf->getArgVars().begin();
386+ std::vector<var_expr*>::const_iterator end = udf->getArgVars().end();
387+ for (; ite != end; ++ite)
388+ {
389+ expr* argVar = (*ite);
390+ if (argVar->inUnsafeContext())
391+ {
392+ expr* argExpr = e->get_arg(ite - udf->getArgVars().begin());
393+ markInUnsafeContext(argExpr);
394+ }
395+ }
396+ } // f->isUdf()
397+ else
398+ {
399+ csize numArgs = e->num_args();
400+ for (csize i = 0; i < numArgs; ++i)
401+ {
402+ if (f->propagatesInputNodes(e, i))
403+ {
404+ markInUnsafeContext(e->get_arg(i));
405+ }
406+ }
407+ }
408+
409+ return;
410+ }
411+
412+ case treat_expr_kind:
413+ case order_expr_kind:
414+ case wrapper_expr_kind:
415+ case function_trace_expr_kind:
416+ case extension_expr_kind:
417+ {
418+ break;
419+ }
420+
421+ case validate_expr_kind:
422+ {
423+ node->setInUnsafeContext(ANNOTATION_TRUE);
424+ return;
425+ }
426+
427+ case transform_expr_kind:
428+ {
429+ transform_expr* e = static_cast<transform_expr *>(node);
430+ e->setInUnsafeContext(ANNOTATION_TRUE);
431+ markInUnsafeContext(e->getReturnExpr());
432+ return;
433+ }
434+
435+ case block_expr_kind:
436+ {
437+ block_expr* e = static_cast<block_expr *>(node);
438+ e->setInUnsafeContext(ANNOTATION_TRUE);
439+ expr* lastChild = (*e)[e->size()-1];
440+ markInUnsafeContext(lastChild);
441+ return;
442+ }
443+
444+ case var_decl_expr_kind:
445+ case var_set_expr_kind:
446+ {
447+ return;
448+ }
449+
450+ case apply_expr_kind:
451+ {
452+ break;
453+ }
454+
455+ case exit_catcher_expr_kind:
456+ {
457+ exit_catcher_expr* e = static_cast<exit_catcher_expr*>(node);
458+
459+ std::vector<expr*>::const_iterator ite = e->exitExprsBegin();
460+ std::vector<expr*>::const_iterator end = e->exitExprsEnd();
461+
462+ for (; ite != end; ++ite)
463+ {
464+ exit_expr* ex = static_cast<exit_expr*>(*ite);
465+
466+ markInUnsafeContext(ex->get_expr());
467+ }
468+
469+ break;
470+ }
471+
472+
473+ case eval_expr_kind:
474+ {
475+ break;
476+ }
477+
478+ case debugger_expr_kind:
479+ {
480+ break; // ????
481+ }
482+
483+ case dynamic_function_invocation_expr_kind:
484+ {
485+ break;
486+ }
487+
488+ case function_item_expr_kind:
489+ {
490+ function_item_expr* e = static_cast<function_item_expr*>(node);
491+
492+ user_function* udf = static_cast<user_function*>(e->get_function());
493+
494+ markInUnsafeContext(udf->getBody());
495+
496+ return;
497+ }
498+
499+ case promote_expr_kind:
500+ case castable_expr_kind:
501+ case cast_expr_kind:
502+ case instanceof_expr_kind:
503+ case name_cast_expr_kind:
504+ case axis_step_expr_kind:
505+ case match_expr_kind:
506+ case delete_expr_kind:
507+ case rename_expr_kind:
508+ case insert_expr_kind:
509+ case replace_expr_kind:
510+ case while_expr_kind:
511+ case flowctl_expr_kind:
512+ case exit_expr_kind:
513+#ifndef ZORBA_NO_FULL_TEXT
514+ case ft_expr_kind:
515+#endif
516+ default:
517+ ZORBA_ASSERT(false);
518+ }
519+
520+ node->setInUnsafeContext(ANNOTATION_TRUE);
521+
522+ ExprIterator iter(node);
523+ while(!iter.done())
524+ {
525+ expr* child = (**iter);
526+ if (child != NULL)
527+ {
528+ markInUnsafeContext(child);
529+ }
530+ iter.next();
531+ }
532+
533+ return;
534+}
535+
536+
537 }
538 /* vim:set et sw=2 ts=2: */
539
540=== modified file 'src/compiler/rewriter/rules/ruleset.h'
541--- src/compiler/rewriter/rules/ruleset.h 2012-10-02 11:57:15 +0000
542+++ src/compiler/rewriter/rules/ruleset.h 2012-10-02 22:52:19 +0000
543@@ -125,11 +125,6 @@
544
545 /*******************************************************************************
546
547- theIsInUnsafeContext:
548- ---------------------
549- If true, it indicates that an expr E1 satisfies a condition that makes a
550- sub-expr E2 of E1 be unsafe, even though E2 by itself is safe.
551-
552 ********************************************************************************/
553 class MarkNodeCopyProps : public RewriteRule
554 {
555@@ -140,13 +135,10 @@
556
557 UdfCalls theProcessedUDFCalls;
558
559- bool theIsInUnsafeContext;
560-
561 public:
562 MarkNodeCopyProps()
563 :
564- RewriteRule(RewriteRule::MarkNodeCopyProps, "MarkNodeCopyProps"),
565- theIsInUnsafeContext(false)
566+ RewriteRule(RewriteRule::MarkNodeCopyProps, "MarkNodeCopyProps")
567 {
568 }
569
570@@ -156,6 +148,8 @@
571 void applyInternal(RewriterContext& rCtx, expr* node, UDFCallChain& udfCaller);
572
573 void markSources(const std::vector<expr*>& sources);
574+
575+ void markInUnsafeContext(expr* node);
576 };
577
578
579
580=== added file 'test/rbkt/ExpQueryResults/zorba/no-copy/test4.xml.res'
581--- test/rbkt/ExpQueryResults/zorba/no-copy/test4.xml.res 1970-01-01 00:00:00 +0000
582+++ test/rbkt/ExpQueryResults/zorba/no-copy/test4.xml.res 2012-10-02 22:52:19 +0000
583@@ -0,0 +1,1 @@
584+<s:name xmlns:s="http://www.zorba-xquery.org/simple">foo</s:name>
585
586=== added file 'test/rbkt/ExpQueryResults/zorba/no-copy/test5.xml.res'
587--- test/rbkt/ExpQueryResults/zorba/no-copy/test5.xml.res 1970-01-01 00:00:00 +0000
588+++ test/rbkt/ExpQueryResults/zorba/no-copy/test5.xml.res 2012-10-02 22:52:19 +0000
589@@ -0,0 +1,1 @@
590+<s:name xmlns:s="http://www.zorba-xquery.org/simple">foo</s:name> true
591
592=== added file 'test/rbkt/Queries/zorba/no-copy/test4.xq'
593--- test/rbkt/Queries/zorba/no-copy/test4.xq 1970-01-01 00:00:00 +0000
594+++ test/rbkt/Queries/zorba/no-copy/test4.xq 2012-10-02 22:52:19 +0000
595@@ -0,0 +1,17 @@
596+
597+declare namespace opt = "http://www.zorba-xquery.com/options/optimizer";
598+
599+declare construction strip;
600+
601+declare copy-namespaces preserve, no-inherit;
602+
603+
604+import schema namespace s="http://www.zorba-xquery.org/simple" at "simple.xsd";
605+
606+declare option opt:enable "for-serialization-only";
607+
608+declare variable $doc := <s:person><s:name>foo</s:name><s:age>25</s:age></s:person>;
609+
610+let $vdoc := validate { $doc }
611+let $copy := <root>{$vdoc/s:name}</root>
612+return $copy/child::element(*, xs:untyped)
613
614=== added file 'test/rbkt/Queries/zorba/no-copy/test5.xq'
615--- test/rbkt/Queries/zorba/no-copy/test5.xq 1970-01-01 00:00:00 +0000
616+++ test/rbkt/Queries/zorba/no-copy/test5.xq 2012-10-02 22:52:19 +0000
617@@ -0,0 +1,16 @@
618+declare namespace opt = "http://www.zorba-xquery.com/options/optimizer";
619+
620+declare construction strip;
621+
622+declare copy-namespaces preserve, no-inherit;
623+
624+import schema namespace s="http://www.zorba-xquery.org/simple" at "simple.xsd";
625+
626+declare option opt:enable "for-serialization-only";
627+
628+declare variable $doc := <s:person><s:name>foo</s:name><s:age>25</s:age></s:person>;
629+
630+let $vdoc := validate { $doc }
631+let $copy := <root>{$vdoc/s:name}</root>
632+let $copyname := $copy/s:name
633+return ($copyname, " ", $copyname instance of element(*, xs:string))

Subscribers

People subscribed via source and target branches