1 /*
2  * Copyright 2006-2008 The FLWOR Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 #ifndef ZORBA_RUNTIME_FNCALL_ITERATOR
18 #define ZORBA_RUNTIME_FNCALL_ITERATOR
19 
20 #include <zorba/api_shared_types.h>
21 #include <zorba/function.h>
22 
23 #include "common/shared_types.h"
24 
25 // TODO remove the next three includes
26 #include "api/unmarshaller.h"
27 #include "context/static_context.h"
28 
29 #include "runtime/base/narybase.h"
30 
31 
32 namespace zorba {
33 
34 class StaticContextImpl;
35 
36 
37 /*******************************************************************************
38   thePlan:
39   --------
40   The runtime plan for the function body. This is created during
41   UDFunctionCallIterator::openImpl(), if it has not not been created already
42   (during the openImpl() method of another UDFunctionCallIterator on the same
43   udf). A pointer to this plan is also stored in the udf obj itself, and that's
44   how we know if it has been created already or not.
45 
46   thePlanState:
47   -------------
48   The plan state to run thePlan with. The PlanState obj is created during
49   UDFunctionCallIterator::openImpl(), but the actual state block is created and
50   initialized the 1st time that UDFunctionCallIterator::nextImpl() is called
51   (at that time open() is invoked on thePlan).
52 
53   thePlanStateSize:
54   -----------------
55   The size of the plan state block.
56 
57   theLocalDCtx:
58   -------------
59   The dynamic context for this udf call. It is where the values of the udf's
60   local block-variables are stored.  It is created during
61   UDFunctionCallIterator::openImpl(),
62 
63   thePlanOpen:
64   ------------
65   Whether thePlan has been opened already or not.
66 
67   theArgWrappers:
68   ---------------
69   For each argument of this function call, theArgWrappers stores a plan iterator
70   wrapper over the sub plan that computes the arg expr. This wrapping is needed
71   because the udf-body plan and the arg sub plans operate in different plan states.
72   Note: Withinh the function body, there may exist more than one references to
73   an arg var V, but these references are "mutually exclusive", ie, at most one
74   of the references will actually be reached during each particular execution of
75   the body. So, it is never the case that the arg expr will have more than one
76   consumers, and as a result we can bind all those V references to the same arg
77   wrapper.
78 
79   theCache:
80   ---------
81   Is an Index which is set in the state if caching for the invoked function
82   should be done. The cache is owned by the UDF itself and shared across
83   all function invocations.
84 
85   theArgValues:
86   -------------
87   If caching is used, this vector contains the results of all arguments
88   of the function evaluation. It's used to bind the arg variables if the
89   cache didn't give a result in order to avoid duplicate evaluation of
90   the arguments.
91 ********************************************************************************/
92 class UDFunctionCallIteratorState : public PlanIteratorState
93 {
94 public:
95   PlanIter_t                       thePlan;
96   PlanState                      * thePlanState;
97   uint32_t                         thePlanStateSize;
98   dynamic_context                * theLocalDCtx;
99   bool                             thePlanOpen;
100   std::vector<store::Iterator_t>   theArgWrappers;
101   store::Index                   * theCache;
102   std::vector<store::TempSeq_t>    theArgValues;
103 
104   UDFunctionCallIteratorState();
105 
106   ~UDFunctionCallIteratorState();
107 
108   void open(PlanState& planState, user_function* udf);
109 
110   void reset(PlanState& planState);
111 };
112 
113 
114 /*******************************************************************************
115   theUDF:
116   -------
117   Pointer to the udf object.
118 
119   theIsDynamic:
120   -------------
121 
122 ********************************************************************************/
123 class UDFunctionCallIterator : public NaryBaseIterator<UDFunctionCallIterator,
124                                                        UDFunctionCallIteratorState>
125 {
126   typedef std::vector<LetVarIter_t> ArgVarRefs;
127 
128 protected:
129   user_function  * theUDF;
130   bool             theIsDynamic;
131 
132 public:
133   SERIALIZABLE_CLASS(UDFunctionCallIterator);
134 
135   SERIALIZABLE_CLASS_CONSTRUCTOR2T(
136   UDFunctionCallIterator,
137   NaryBaseIterator<UDFunctionCallIterator, UDFunctionCallIteratorState>);
138 
139   void serialize(::zorba::serialization::Archiver& ar);
140 
141 public:
142   UDFunctionCallIterator(
143         static_context* sctx,
144         const QueryLoc& loc,
145         std::vector<PlanIter_t>& args,
146         const user_function* aUDF);
147 
~UDFunctionCallIterator()148   ~UDFunctionCallIterator() {}
149 
150   bool isUpdating() const;
151 
setDynamic()152   void setDynamic() { theIsDynamic = true; }
153 
154   bool isCached() const;
155 
156   void accept(PlanIterVisitor& v) const;
157 
158   void openImpl(PlanState& planState, uint32_t& offset);
159 
160   void resetImpl(PlanState& planState) const;
161 
162   void closeImpl(PlanState& planState);
163 
164   bool nextImpl(store::Item_t& result, PlanState& planState) const;
165 
166 protected:
167   void createCache(
168     PlanState& planState,
169     UDFunctionCallIteratorState* state);
170 
171   bool probeCache(
172     PlanState& planState,
173     UDFunctionCallIteratorState* state,
174     store::Item_t& result,
175     std::vector<store::Item_t>& argValues) const;
176 
177   void insertCacheEntry(
178     UDFunctionCallIteratorState* state,
179     std::vector<store::Item_t>& argValues,
180     store::Item_t& udfValue) const;
181 };
182 
183 
184 /*******************************************************************************
185 
186 ********************************************************************************/
187 class ExtFunctionCallIteratorState : public PlanIteratorState
188 {
189  public:
190   std::vector<ItemSequence*> m_extArgs;
191   ItemSequence_t             theResult;
192   Iterator_t                 theResultIter;
193 
194   ExtFunctionCallIteratorState();
195 
196   ~ExtFunctionCallIteratorState();
197 
198   void reset(PlanState&);
199 };
200 
201 
202 class ExtFunctionCallIterator : public NaryBaseIterator<ExtFunctionCallIterator,
203                                                         ExtFunctionCallIteratorState>
204 {
205 protected:
206   const ExternalFunction * theFunction;
207   bool                     theIsUpdating;
208   zstring                  theNamespace;
209   static_context         * theModuleSctx;
210 
211 public:
212   SERIALIZABLE_CLASS(ExtFunctionCallIterator);
213 
214   SERIALIZABLE_CLASS_CONSTRUCTOR2T(
215   ExtFunctionCallIterator,
216   NaryBaseIterator<ExtFunctionCallIterator, ExtFunctionCallIteratorState>);
217 
218   void serialize(serialization::Archiver& ar);
219 
220 public:
221   ExtFunctionCallIterator(
222         static_context* sctx,
223         const QueryLoc& loc,
224         std::vector<PlanIter_t>& args,
225         const ExternalFunction* function,
226         bool isUpdating,
227         const zstring& ns,
228         static_context* moduleSctx);
229 
230   virtual ~ExtFunctionCallIterator();
231 
isUpdating()232   virtual bool isUpdating() const { return theIsUpdating; }
233 
234   void accept(PlanIterVisitor& v) const;
235 
236   void openImpl(PlanState& planState, uint32_t& offset);
237 
238   bool nextImpl(store::Item_t& result, PlanState& planState) const;
239 };
240 
241 }
242 
243 #endif /* ZORBA_FNCALL_ITERATOR_H */
244 
245 /*
246  * Local variables:
247  * mode: c++
248  * End:
249  */
250 /* vim:set et sw=2 ts=2: */
251