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_API_XQUERY_IMPL
18 #define ZORBA_API_XQUERY_IMPL
19 
20 #include <iostream>
21 #include <zorba/xquery.h>
22 #include <zorba/sax2.h>
23 
24 #include <zorba/api_shared_types.h>
25 
26 #include "zorbautils/mutex.h"
27 
28 #include "common/shared_types.h"
29 
30 #include "zorbaserialization/class_serializer.h"
31 
32 
33 namespace zorba
34 {
35 
36 class RCObject;
37 #ifdef ZORBA_WITH_DEBUGGER
38 class ZorbaDebugger;
39 class DebuggerRuntime;
40 class DebuggerCommons;
41 #endif
42 class DynamicContextImpl;
43 class StaticContextImpl;
44 class ResultIteratorImpl;
45 class dynamic_context;
46 class CompilerCB;
47 class StaticCollectionManagerSetImpl;
48 
49 
50 /*******************************************************************************
51 
52   - theFileName :
53   The filename of the file containing the query. It is taken into account when
54   computing the base uri property of the static context. It may be an empty
55   string, if query does not come from a file.
56 
57   - theStaticContext :
58   rchandle to the root sctx obj for this xquery. This sctx may be (a) a child
59   of the zorba root sctx, or (b) a child of an sctx that was created by the
60   application, or (c) if this XQuery obj is a clone of another XQuery obj, a
61   child of the root sctx of the other XQuery obj, or (d) if this XQuery obj
62   is one that is created internally by StaticContextImpl::loadProlog(), the
63   sctx that was created by the application. In cases (a), (b), and (c), the
64   root sctx of the query is created by the xquery obj itself.
65 
66   - theStaticContextWrapper :
67   Pointer to a StaticContextImpl obj that wraps theStaticContext and which is
68   created when the application asks for the static context of the query (see
69   getStaticContext() method). The pointer is cached, so that it is returned
70   if the application askes for the static context again.
71 
72   - theCompilerCB :
73   A CompilerCB obj provides some additional context that is needed during the
74   compilation and execution of a query. See src/compiler/api/compilercb.h for
75   deetails. Each xquery obj has its own associated CompilerCB obj, which is
76   created by the constructor of the xquery obj.
77 
78   - thePlanProxy :
79   An rchandle to a PlanProxy obj that provides thread-safe access to the root
80   iterator of the plan iterator tree. A PlanProxy obj is needed for thread
81   safety, because the plan is shared among cloned queries, but the PlanIterator
82   class does not do thread-safe ref counting. All clones share the same
83   PlanProxy obj, which is a sunchronized RCObject. This way, no ref count
84   ops are performed on the plan root, except when the plan proxy itself is
85   destroyed, which can be done by a single therad only.
86 
87   - theDynamicContext :
88   The dynamic context for this query. Always belongs to the query. It is created
89   by the XQueryImpl constructor.
90 
91   - theDynamicContextWrapper :
92 
93   - theResultIterator :
94   There is an 0:1 relationship between ResultIterator and XQuery objs. This
95   relationship is implemented by (a) theResultIterator, which is a ptr to
96   a ResultIterator that has been created by the XQuery::iterator() method,
97   and (b) a ptr in this ResultIterator pointing back to the associated
98   XQuery. This way we can guarantee that no ResultIterator exists when its
99   associated XQuery is closed (see ~ResultIterator() and XQuery::close()).
100 
101   - theIsClosed :
102   Set to true when the query has been closed. Used to check that after closing
103   a query, no operations can be performed on that query anymore.
104 
105   - theExecuting :
106   Set to true while the query is being executed. It is used to make sure that
107   a second execution of the same XQuery obj cannot be started while a previous
108   execution is still going on.
109 
110   - theXQueryDiagnostics :
111   Each query has its own XQueryDiagnostics. The XQueryDiagnostics accumulates
112   query errors/warnings that need to be processed in some deferred fashion.
113 
114   - theDiagnosticHandler :
115   Normally, this is an object provided by the application to handle errors in
116   some specific way (see include/zorba/diagnostic_handler.h and src/api/zorbaimpl.cpp).
117   If the application does not provide an error handler, a default zorba error
118   handler is created for the query (the default error handler just throws a
119   ZorbaException).
120 
121   - theUserDiagnosticHandler :
122   True if the error handler was provided by the application (in which case it
123   is not owned by the query). Also true if this is a cloned query, in which
124   case, theDiagnosticHandler points to the same error handler obj as the orignal
125   query. False otherwise (in which case the error handler is owned by the
126   query).
127 
128   - theSAX2Handler :
129   sax content handler that provide event-based xml parser
130 
131   - theIsDebugMode :
132 
133   - theProfileName :
134 
135   - theStaticCollectionMgr :
136   StaticCollectionManager object for all statically declared collections in this
137   query or any transitively imported module. It's created lazily upon request
138   and destroyed when this XQueryImpl object is destroyed.
139 
140 ********************************************************************************/
141 class XQueryImpl : public XQuery , public ::zorba::serialization::SerializeBaseClass
142 {
143   friend class ResultIteratorImpl;
144   friend class StaticContextImpl;  // StaticContextImpl::loadProlog() needs this
145   friend class DynamicContextImpl;
146   friend class CompilerCB;
147 #ifdef ZORBA_WITH_DEBUGGER
148   friend class ZorbaDebugger;
149   friend class DebuggerRuntime;
150 #endif
151 
152  protected:
153 
154   class PlanProxy : public RCObject
155   {
156   public:
157     SYNC_CODE(mutable RCLock  theRCLock;)
158 
159     rchandle<SimpleRCObject>  theRootIter;
160 
161   public:
162     SERIALIZABLE_CLASS(PlanProxy)
163     SERIALIZABLE_CLASS_CONSTRUCTOR2(PlanProxy, RCObject)
164     void serialize(::zorba::serialization::Archiver& ar);
165 
166   public:
getSharedRefCounter()167     long* getSharedRefCounter() const { return NULL; }
168 
169     SYNC_CODE(virtual RCLock* getRCLock() const { return &theRCLock; })
170 
171     PlanProxy(PlanIter_t& root);
172   };
173 
174   typedef rchandle<PlanProxy> PlanProxy_t;
175 
176  protected:
177 
178   SYNC_CODE(mutable Mutex            theMutex;)
179 
180   // static stuff
181   zstring                            theFileName;
182 
183   static_context_t                   theStaticContext;
184 
185   mutable StaticContextImpl        * theStaticContextWrapper;
186 
187   CompilerCB                       * theCompilerCB;
188 
189   PlanProxy_t                        thePlanProxy;
190 
191   // dynamic stuff
192   dynamic_context                  * theDynamicContext;
193 
194   mutable DynamicContextImpl       * theDynamicContextWrapper;
195 
196   ResultIteratorImpl               * theResultIterator;
197 
198   bool                               theExecuting;
199 
200   bool                               theIsClosed;
201 
202   // utility stuff
203   XQueryDiagnostics                * theXQueryDiagnostics;
204   DiagnosticHandler                * theDiagnosticHandler;
205   bool                               theUserDiagnosticHandler;
206 
207   SAX2_ContentHandler              * theSAX2Handler;
208 
209   double                             theDocLoadingUserTime;
210   double                             theDocLoadingTime;
211 
212 private:
213 #ifdef ZORBA_WITH_DEBUGGER
214   bool                               theIsDebugMode;
215 #endif
216   std::string                        theProfileName;
217 
218   mutable StaticCollectionManagerSetImpl* theCollMgr;
219 
220 public:
221   SERIALIZABLE_CLASS(XQueryImpl)
222   XQueryImpl(::zorba::serialization::Archiver& ar);
223   void serialize(::zorba::serialization::Archiver& ar);
224 
225 public:
226   XQueryImpl();
227 
228   ~XQueryImpl();
229 
230   void setFileName(const String&);
231 
232   String getFileName();
233 
234   void setTimeout(long aTimeout /* = -1 */);
235 
236   double getDocLoadingUserTime() const;
237 
238   double getDocLoadingTime() const;
239 
240 #ifdef ZORBA_WITH_DEBUGGER
241   void setDebugMode(bool aDebugMode);
242 
243   bool isDebugMode() const;
244 #endif
245 
246   void setProfileName(std::string aProfileName);
247 
248   std::string getProfileName() const;
249 
250   void registerDiagnosticHandler(DiagnosticHandler*);
251 
252   DiagnosticHandler* getRegisteredDiagnosticHandler();
253 
254   DiagnosticHandler* getRegisteredDiagnosticHandlerNoSync();
255 
256   void resetDiagnosticHandler();
257 
258   void compile(const String&);
259 
260   void compile(
261         const String&,
262         const Zorba_CompilerHints_t& aHints);
263 
264   void compile(
265         const String&,
266         const StaticContext_t&,
267         const Zorba_CompilerHints_t& aHints);
268 
269   void compile(
270         std::istream&,
271         const Zorba_CompilerHints_t& aHints);
272 
273   void compile(
274         std::istream&,
275         const StaticContext_t&,
276         const Zorba_CompilerHints_t& aHints);
277 
278   void loadProlog(
279         const String&,
280         const StaticContext_t&,
281         const Zorba_CompilerHints_t& aHints);
282 
283   void parse(std::istream&);
284 
285   const StaticContext* getStaticContext() const;
286 
287   void getExternalVariables(Iterator_t& aVarsIter) const;
288 
289   bool isUpdating() const;
290 
291   bool isSequential() const;
292 
293   bool saveExecutionPlan(
294         std::ostream& os,
295         Zorba_binary_plan_format_t archive_format = ZORBA_USE_BINARY_ARCHIVE,
296         Zorba_save_plan_options_t save_options = DONT_SAVE_UNUSED_FUNCTIONS);
297 
298   bool loadExecutionPlan(std::istream& is, SerializationCallback* aCallback = 0);
299 
300   void printPlan(std::ostream& aStream, bool aDotFormat = false) const;
301 
302   DynamicContext* getDynamicContext() const;
303 
304   void execute(std::ostream&, const Zorba_SerializerOptions_t* = NULL);
305 
306   void execute(
307         std::ostream& aOutStream,
308         itemHandler aCallbackFunction,
309         void* aCallbackData,
310         const Zorba_SerializerOptions_t* aSerOptions = NULL);
311 
312   void execute();
313 
314   Iterator_t iterator();
315 
316   void registerSAXHandler(SAX2_ContentHandler* aSAXHandler);
317 
318   void executeSAX(SAX2_ContentHandler* aSAXHandler);
319 
320   void executeSAX();
321 
322 #ifdef ZORBA_WITH_DEBUGGER
323   void
324   debug(
325     const std::string& host,
326     unsigned short port);
327 
328   virtual void
329   debug(
330     std::ostream& outStream,
331     Zorba_SerializerOptions& serOptions,
332     const std::string& host,
333     unsigned short port);
334 
335   void
336   debug(
337     std::ostream& outStream,
338     itemHandler callbackFunction,
339     void* callbackData,
340     Zorba_SerializerOptions& serOptions,
341     const std::string& host,
342     unsigned short port);
343 #endif
344 
345   void close();
346 
isClosed()347   bool isClosed() const { return theIsClosed; }
348 
349   XQuery_t clone() const;
350 
351   StaticCollectionManager*
352   getStaticCollectionManager() const;
353 
354 protected:
355 
356   void doCompile(
357         std::istream&,
358         const Zorba_CompilerHints_t& aHints,
359         bool fork_sctx,
360         ulong& nextVarId);
361 
362   PlanWrapper_t generateWrapper();
363 
364   // special serialize and applyUpdate function that is used by debugger
365   // and by the public serialize and applyUpdate functions, respectively.
366   // they are passed an opened PlanWrapper
367   // important: this function does not (read/write) lock the store. this
368   // needs to be done by the caller of this function
369   // also note that the PlanWrapper that is passed to this function needs
370   // to be generated by the generateWrapper of the same object
371   // there is currently no check that enforces this
372   // after this function has finished, the PlanWrapper also needs to be
373   // closed by the caller
374   void serialize(
375         std::ostream&,
376         PlanWrapper_t& aWrapper,
377         const Zorba_SerializerOptions_t* = NULL);
378 
379   void serialize(
380         std::ostream&,
381         PlanWrapper_t& aWrapper,
382         itemHandler aHandler,
383         void* aHandlerData,
384         const Zorba_SerializerOptions_t* = NULL);
385 
386   void removeResultIterator(const ResultIteratorImpl* iter);
387 
388   void checkNotClosed() const;
389 
390   void checkCompiled() const;
391 
392   void checkNotCompiled() const;
393 
394   void checkNotExecuting() const;
395 
396 #ifdef ZORBA_WITH_DEBUGGER
397   void checkIsDebugMode() const;
398 #endif
399 
400   void notifyAllWarnings() const;
401 
402   bool isBoundVariable(const String& aNamespace, const String& aLocalname) const;
403 };
404 
405 
406 std::ostream& operator<< (std::ostream& os, const XQuery_t& aQuery);
407 
408 std::ostream& operator<< (std::ostream& os, XQuery* aQuery);
409 
410 
411 } /* namespace zorba */
412 #endif
413 
414 /*
415  * Local variables:
416  * mode: c++
417  * End:
418  */
419 /* vim:set et sw=2 ts=2: */
420