Merge lp:~zorba-coders/zorba/fix-fncall-iterator into lp:zorba
- fix-fncall-iterator
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 11714 |
Proposed branch: | lp:~zorba-coders/zorba/fix-fncall-iterator |
Merge into: | lp:zorba |
Diff against target: |
336 lines (+136/-122) 4 files modified
src/runtime/core/fncall_iterator.cpp (+126/-122) src/runtime/core/fncall_iterator.h (+5/-0) test/rbkt/ExpQueryResults/zorba/file/file_read_text_lines-2.xml.res (+1/-0) test/rbkt/Queries/zorba/file/file_read_text_lines-2.xq (+4/-0) |
To merge this branch: | bzr merge lp:~zorba-coders/zorba/fix-fncall-iterator |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Federico Cavalieri | Approve | ||
Matthias Brantner | Approve | ||
Review via email: mp+215934@code.launchpad.net |
Commit message
Fixed external functions skip iterator
Description of the change
Fixed external functions skip iterator
Federico Cavalieri (fcavalieri) wrote : | # |
- 11714. By Federico Cavalieri
-
Fixed external functions skip iterator
Matthias Brantner (matthias-brantner) : | # |
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue starting for the following merge proposals:
https:/
Progress dashboard at http://
Zorba Build Bot (zorba-buildbot) wrote : | # |
Voting criteria failed for the following merge proposals:
https:/
Votes: {'Approve': 1}
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue result for https:/
Stage "CommitZorba" failed.
Check console output at http://
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue starting for the following merge proposals:
https:/
Progress dashboard at http://
Zorba Build Bot (zorba-buildbot) wrote : | # |
Voting criteria failed for the following merge proposals:
https:/
Votes: {'Approve': 1}
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue result for https:/
Stage "CommitZorba" failed.
Check console output at http://
Federico Cavalieri (fcavalieri) : | # |
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue starting for the following merge proposals:
https:/
Progress dashboard at http://
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue succeeded - proposal merged!
Preview Diff
1 | === modified file 'src/runtime/core/fncall_iterator.cpp' | |||
2 | --- src/runtime/core/fncall_iterator.cpp 2014-02-25 03:58:17 +0000 | |||
3 | +++ src/runtime/core/fncall_iterator.cpp 2014-04-15 19:36:22 +0000 | |||
4 | @@ -773,7 +773,8 @@ | |||
5 | 773 | /******************************************************************************* | 773 | /******************************************************************************* |
6 | 774 | 774 | ||
7 | 775 | ********************************************************************************/ | 775 | ********************************************************************************/ |
9 | 776 | ExtFunctionCallIteratorState::ExtFunctionCallIteratorState() | 776 | ExtFunctionCallIteratorState::ExtFunctionCallIteratorState(): |
10 | 777 | theIsEvaluated(false) | ||
11 | 777 | { | 778 | { |
12 | 778 | } | 779 | } |
13 | 779 | 780 | ||
14 | @@ -796,6 +797,7 @@ | |||
15 | 796 | PlanIteratorState::reset(planState); | 797 | PlanIteratorState::reset(planState); |
16 | 797 | theResultIter = NULL; | 798 | theResultIter = NULL; |
17 | 798 | theResult = NULL; | 799 | theResult = NULL; |
18 | 800 | theIsEvaluated = false; | ||
19 | 799 | } | 801 | } |
20 | 800 | 802 | ||
21 | 801 | 803 | ||
22 | @@ -951,48 +953,43 @@ | |||
23 | 951 | STACK_END( state ); | 953 | STACK_END( state ); |
24 | 952 | } | 954 | } |
25 | 953 | 955 | ||
28 | 954 | bool ExtFunctionCallIterator::skip( int64_t count, | 956 | bool ExtFunctionCallIterator::skip(int64_t count, PlanState &planState) const |
29 | 955 | PlanState &planState ) const { | 957 | { |
30 | 958 | if (count == 0) | ||
31 | 959 | return true; | ||
32 | 960 | |||
33 | 956 | ItemSequence_t api_seq; | 961 | ItemSequence_t api_seq; |
34 | 957 | bool more_items; | 962 | bool more_items; |
65 | 958 | 963 | ExtFunctionCallIteratorState *state = | |
66 | 959 | ExtFunctionCallIteratorState *state; | 964 | StateTraitsImpl<ExtFunctionCallIteratorState>::getState(planState, this->theStateOffset); |
67 | 960 | DEFAULT_STACK_INIT( ExtFunctionCallIteratorState, state, planState ); | 965 | |
68 | 961 | 966 | try | |
69 | 962 | try { | 967 | { |
70 | 963 | if ( theFunction->isContextual() ) { | 968 | ZORBA_ASSERT(!state->theIsEvaluated); |
71 | 964 | ContextualExternalFunction const *const f = | 969 | evaluate(state, planState); |
72 | 965 | dynamic_cast<ContextualExternalFunction const*>( theFunction ); | 970 | |
73 | 966 | ZORBA_ASSERT( f ); | 971 | if ( !state->theResult.isNull() ) |
74 | 967 | StaticContextImpl sctx( | 972 | { |
75 | 968 | theModuleSctx, | 973 | state->theResultIter = state->theResult->getIterator(); |
76 | 969 | planState.theQuery ? | 974 | state->theResultIter->open(); |
77 | 970 | planState.theQuery->getRegisteredDiagnosticHandlerNoSync() : | 975 | more_items = state->theResultIter->skip( count ); |
78 | 971 | nullptr | 976 | if (!more_items) |
79 | 972 | ); | 977 | state->theResultIter->close(); |
50 | 973 | DynamicContextImpl dctx( | ||
51 | 974 | nullptr, planState.theGlobalDynCtx, theModuleSctx | ||
52 | 975 | ); | ||
53 | 976 | api_seq = f->evaluate( state->m_extArgs, &sctx, &dctx ); | ||
54 | 977 | } else { | ||
55 | 978 | NonContextualExternalFunction const *const f = | ||
56 | 979 | dynamic_cast<NonContextualExternalFunction const*>( theFunction ); | ||
57 | 980 | ZORBA_ASSERT( f ); | ||
58 | 981 | api_seq = f->evaluate( state->m_extArgs ); | ||
59 | 982 | } | ||
60 | 983 | if ( !!api_seq ) { | ||
61 | 984 | Iterator_t api_iter( api_seq->getIterator() ); | ||
62 | 985 | api_iter->open(); | ||
63 | 986 | more_items = api_iter->skip( count ); | ||
64 | 987 | api_iter->close(); | ||
80 | 988 | } | 978 | } |
81 | 989 | } | 979 | } |
83 | 990 | catch ( ZorbaException &e ) { | 980 | catch ( ZorbaException &e ) |
84 | 981 | { | ||
85 | 991 | set_source( e, loc ); | 982 | set_source( e, loc ); |
86 | 992 | throw; | 983 | throw; |
87 | 993 | } | 984 | } |
90 | 994 | STACK_PUSH( more_items, state ); | 985 | catch (std::exception const& e) |
91 | 995 | STACK_END( state ); | 986 | { |
92 | 987 | throw XQUERY_EXCEPTION( | ||
93 | 988 | zerr::ZXQP0001_DYNAMIC_RUNTIME_ERROR, | ||
94 | 989 | ERROR_PARAMS(e.what()), | ||
95 | 990 | ERROR_LOC(loc)); | ||
96 | 991 | } | ||
97 | 992 | return more_items; | ||
98 | 996 | } | 993 | } |
99 | 997 | 994 | ||
100 | 998 | bool ExtFunctionCallIterator::nextImpl( | 995 | bool ExtFunctionCallIterator::nextImpl( |
101 | @@ -1000,102 +997,109 @@ | |||
102 | 1000 | PlanState& planState) const | 997 | PlanState& planState) const |
103 | 1001 | { | 998 | { |
104 | 1002 | Item lOutsideItem; | 999 | Item lOutsideItem; |
105 | 1003 | const NonContextualExternalFunction* lPureFct = 0; | ||
106 | 1004 | const ContextualExternalFunction* lNonePureFct = 0; | ||
107 | 1005 | 1000 | ||
108 | 1006 | ExtFunctionCallIteratorState* state; | 1001 | ExtFunctionCallIteratorState* state; |
109 | 1007 | DEFAULT_STACK_INIT(ExtFunctionCallIteratorState, state, planState); | 1002 | DEFAULT_STACK_INIT(ExtFunctionCallIteratorState, state, planState); |
110 | 1008 | 1003 | ||
165 | 1009 | try | 1004 | if (!state->theIsEvaluated) |
112 | 1010 | { | ||
113 | 1011 | if (!theFunction->isContextual()) | ||
114 | 1012 | { | ||
115 | 1013 | lPureFct = dynamic_cast<const NonContextualExternalFunction*>(theFunction); | ||
116 | 1014 | ZORBA_ASSERT(lPureFct); | ||
117 | 1015 | |||
118 | 1016 | state->theResult = lPureFct->evaluate(state->m_extArgs); | ||
119 | 1017 | if(state->theResult.get() != NULL) | ||
120 | 1018 | state->theResultIter = state->theResult->getIterator(); | ||
121 | 1019 | } | ||
122 | 1020 | else | ||
123 | 1021 | { | ||
124 | 1022 | lNonePureFct = dynamic_cast<const ContextualExternalFunction*>(theFunction); | ||
125 | 1023 | ZORBA_ASSERT(lNonePureFct); | ||
126 | 1024 | |||
127 | 1025 | // The planState.theQuery maybe null, e.g. in the case of constant-folding | ||
128 | 1026 | // of global variable expressions | ||
129 | 1027 | StaticContextImpl theSctxWrapper(theModuleSctx, | ||
130 | 1028 | (planState.theQuery == NULL? | ||
131 | 1029 | NULL : | ||
132 | 1030 | planState.theQuery->getRegisteredDiagnosticHandlerNoSync())); | ||
133 | 1031 | |||
134 | 1032 | DynamicContextImpl theDctxWrapper(NULL, | ||
135 | 1033 | planState.theGlobalDynCtx, | ||
136 | 1034 | theModuleSctx); | ||
137 | 1035 | |||
138 | 1036 | state->theResult = lNonePureFct->evaluate(state->m_extArgs, | ||
139 | 1037 | &theSctxWrapper, | ||
140 | 1038 | &theDctxWrapper); | ||
141 | 1039 | |||
142 | 1040 | if(state->theResult.get() != NULL) | ||
143 | 1041 | state->theResultIter = state->theResult->getIterator(); | ||
144 | 1042 | } // if (!theFunction->isContextual()) | ||
145 | 1043 | } | ||
146 | 1044 | catch (ZorbaException& e) | ||
147 | 1045 | { | ||
148 | 1046 | set_source( e, loc ); | ||
149 | 1047 | throw; | ||
150 | 1048 | } | ||
151 | 1049 | catch (std::exception const& e) | ||
152 | 1050 | { | ||
153 | 1051 | throw XQUERY_EXCEPTION( | ||
154 | 1052 | zerr::ZXQP0001_DYNAMIC_RUNTIME_ERROR, | ||
155 | 1053 | ERROR_PARAMS(e.what()), | ||
156 | 1054 | ERROR_LOC(loc)); | ||
157 | 1055 | } | ||
158 | 1056 | |||
159 | 1057 | |||
160 | 1058 | if(state->theResult.get() != NULL) | ||
161 | 1059 | { | ||
162 | 1060 | state->theResultIter->open(); | ||
163 | 1061 | } | ||
164 | 1062 | while (true) | ||
166 | 1063 | { | 1005 | { |
167 | 1064 | try | 1006 | try |
168 | 1065 | { | 1007 | { |
199 | 1066 | if (state->theResult.get() == NULL) // This will happen if the user's external function returns a zorba::ItemSequence_t(NULL) | 1008 | evaluate(state, planState); |
200 | 1067 | break; | 1009 | |
201 | 1068 | 1010 | if (state->theResult.get() != NULL) | |
202 | 1069 | if (!state->theResultIter->next(lOutsideItem)) | 1011 | { |
203 | 1070 | { | 1012 | state->theResultIter = state->theResult->getIterator(); |
204 | 1071 | state->theResultIter->close(); | 1013 | state->theResultIter->open(); |
205 | 1072 | break; | 1014 | } |
206 | 1073 | } | 1015 | } |
207 | 1074 | } | 1016 | catch (ZorbaException& e) |
208 | 1075 | catch (XQueryException& e) | 1017 | { |
209 | 1076 | { | 1018 | set_source( e, loc ); |
210 | 1077 | set_source( e, loc ); | 1019 | throw; |
211 | 1078 | throw; | 1020 | } |
212 | 1079 | } | 1021 | catch (std::exception const& e) |
213 | 1080 | 1022 | { | |
214 | 1081 | result = Unmarshaller::getInternalItem(lOutsideItem); | 1023 | throw XQUERY_EXCEPTION( |
215 | 1082 | 1024 | zerr::ZXQP0001_DYNAMIC_RUNTIME_ERROR, | |
216 | 1083 | if (theIsUpdating) | 1025 | ERROR_PARAMS(e.what()), |
217 | 1084 | { | 1026 | ERROR_LOC(loc)); |
218 | 1085 | if (!result->isPul()) | 1027 | } |
219 | 1086 | throw XQUERY_EXCEPTION(err::XUDY0019, ERROR_LOC(loc)); | 1028 | } |
220 | 1087 | } | 1029 | |
221 | 1088 | else | 1030 | if (!state->theResult.isNull() && //The external function returns zorba::ItemSequence_t(NULL) |
222 | 1089 | { | 1031 | state->theResultIter->isOpen()) //The iterator has not been skipped past its end |
223 | 1090 | if (result->isPul()) | 1032 | { |
224 | 1091 | throw XQUERY_EXCEPTION(err::XUDY0018, ERROR_LOC(loc)); | 1033 | while (true) |
225 | 1092 | } | 1034 | { |
226 | 1093 | STACK_PUSH(true, state); | 1035 | try |
227 | 1094 | } | 1036 | { |
228 | 1095 | 1037 | if (!state->theResultIter->next(lOutsideItem)) | |
229 | 1038 | { | ||
230 | 1039 | state->theResultIter->close(); | ||
231 | 1040 | break; | ||
232 | 1041 | } | ||
233 | 1042 | } | ||
234 | 1043 | catch (XQueryException& e) | ||
235 | 1044 | { | ||
236 | 1045 | set_source( e, loc ); | ||
237 | 1046 | throw; | ||
238 | 1047 | } | ||
239 | 1048 | catch (std::exception const& e) | ||
240 | 1049 | { | ||
241 | 1050 | throw XQUERY_EXCEPTION( | ||
242 | 1051 | zerr::ZXQP0001_DYNAMIC_RUNTIME_ERROR, | ||
243 | 1052 | ERROR_PARAMS(e.what()), | ||
244 | 1053 | ERROR_LOC(loc)); | ||
245 | 1054 | } | ||
246 | 1055 | |||
247 | 1056 | result = Unmarshaller::getInternalItem(lOutsideItem); | ||
248 | 1057 | |||
249 | 1058 | if (theIsUpdating) | ||
250 | 1059 | { | ||
251 | 1060 | if (!result->isPul()) | ||
252 | 1061 | throw XQUERY_EXCEPTION(err::XUDY0019, ERROR_LOC(loc)); | ||
253 | 1062 | } | ||
254 | 1063 | else | ||
255 | 1064 | { | ||
256 | 1065 | if (result->isPul()) | ||
257 | 1066 | throw XQUERY_EXCEPTION(err::XUDY0018, ERROR_LOC(loc)); | ||
258 | 1067 | } | ||
259 | 1068 | STACK_PUSH(true, state); | ||
260 | 1069 | } | ||
261 | 1070 | } | ||
262 | 1096 | STACK_END (state); | 1071 | STACK_END (state); |
263 | 1097 | } | 1072 | } |
264 | 1098 | 1073 | ||
265 | 1074 | void ExtFunctionCallIterator::evaluate(ExtFunctionCallIteratorState* state, PlanState& planState) const | ||
266 | 1075 | { | ||
267 | 1076 | if ( theFunction->isContextual() ) | ||
268 | 1077 | { | ||
269 | 1078 | ContextualExternalFunction const *const lFunction = | ||
270 | 1079 | dynamic_cast<ContextualExternalFunction const*>( theFunction ); | ||
271 | 1080 | ZORBA_ASSERT( lFunction ); | ||
272 | 1081 | |||
273 | 1082 | StaticContextImpl lSctx(theModuleSctx, | ||
274 | 1083 | planState.theQuery ? | ||
275 | 1084 | planState.theQuery->getRegisteredDiagnosticHandlerNoSync(): | ||
276 | 1085 | nullptr); | ||
277 | 1086 | |||
278 | 1087 | DynamicContextImpl lDctx(nullptr, | ||
279 | 1088 | planState.theGlobalDynCtx, | ||
280 | 1089 | theModuleSctx); | ||
281 | 1090 | |||
282 | 1091 | state->theResult = lFunction->evaluate( state->m_extArgs, &lSctx, &lDctx ); | ||
283 | 1092 | } | ||
284 | 1093 | else | ||
285 | 1094 | { | ||
286 | 1095 | NonContextualExternalFunction const *const lFunction = | ||
287 | 1096 | dynamic_cast<NonContextualExternalFunction const*>( theFunction ); | ||
288 | 1097 | ZORBA_ASSERT( lFunction ); | ||
289 | 1098 | |||
290 | 1099 | state->theResult = lFunction->evaluate( state->m_extArgs ); | ||
291 | 1100 | } | ||
292 | 1101 | state->theIsEvaluated = true; | ||
293 | 1102 | } | ||
294 | 1099 | 1103 | ||
295 | 1100 | NARY_ACCEPT(ExtFunctionCallIterator); | 1104 | NARY_ACCEPT(ExtFunctionCallIterator); |
296 | 1101 | 1105 | ||
297 | 1102 | 1106 | ||
298 | === modified file 'src/runtime/core/fncall_iterator.h' | |||
299 | --- src/runtime/core/fncall_iterator.h 2014-02-12 02:25:45 +0000 | |||
300 | +++ src/runtime/core/fncall_iterator.h 2014-04-15 19:36:22 +0000 | |||
301 | @@ -215,6 +215,7 @@ | |||
302 | 215 | std::vector<ItemSequence*> m_extArgs; | 215 | std::vector<ItemSequence*> m_extArgs; |
303 | 216 | ItemSequence_t theResult; | 216 | ItemSequence_t theResult; |
304 | 217 | Iterator_t theResultIter; | 217 | Iterator_t theResultIter; |
305 | 218 | bool theIsEvaluated; | ||
306 | 218 | 219 | ||
307 | 219 | ExtFunctionCallIteratorState(); | 220 | ExtFunctionCallIteratorState(); |
308 | 220 | 221 | ||
309 | @@ -265,7 +266,11 @@ | |||
310 | 265 | bool nextImpl(store::Item_t& result, PlanState& planState) const; | 266 | bool nextImpl(store::Item_t& result, PlanState& planState) const; |
311 | 266 | 267 | ||
312 | 267 | bool count(store::Item_t& result, PlanState& planState) const; | 268 | bool count(store::Item_t& result, PlanState& planState) const; |
313 | 269 | |||
314 | 268 | bool skip(int64_t count, PlanState &planState) const; | 270 | bool skip(int64_t count, PlanState &planState) const; |
315 | 271 | |||
316 | 272 | private: | ||
317 | 273 | void evaluate(ExtFunctionCallIteratorState* state, PlanState& planState) const; | ||
318 | 269 | }; | 274 | }; |
319 | 270 | 275 | ||
320 | 271 | } | 276 | } |
321 | 272 | 277 | ||
322 | === added file 'test/rbkt/ExpQueryResults/zorba/file/file_read_text_lines-2.xml.res' | |||
323 | --- test/rbkt/ExpQueryResults/zorba/file/file_read_text_lines-2.xml.res 1970-01-01 00:00:00 +0000 | |||
324 | +++ test/rbkt/ExpQueryResults/zorba/file/file_read_text_lines-2.xml.res 2014-04-15 19:36:22 +0000 | |||
325 | @@ -0,0 +1,1 @@ | |||
326 | 1 | <products> <product> | ||
327 | 0 | \ No newline at end of file | 2 | \ No newline at end of file |
328 | 1 | 3 | ||
329 | === added file 'test/rbkt/Queries/zorba/file/file_read_text_lines-2.xq' | |||
330 | --- test/rbkt/Queries/zorba/file/file_read_text_lines-2.xq 1970-01-01 00:00:00 +0000 | |||
331 | +++ test/rbkt/Queries/zorba/file/file_read_text_lines-2.xq 2014-04-15 19:36:22 +0000 | |||
332 | @@ -0,0 +1,4 @@ | |||
333 | 1 | import module namespace file = "http://expath.org/ns/file"; | ||
334 | 2 | |||
335 | 3 | file:read-text-lines(fn:resolve-uri("mydata.xml"))[1], | ||
336 | 4 | file:read-text-lines(fn:resolve-uri("mydata.xml"))[2] |
I found a regression, investigating