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
17 #include <iostream>
18 #include <fstream>
19 #include <sstream>
20
21 #include <zorba/zorba.h>
22 #include <zorba/store_manager.h>
23 #include <zorba/uri_resolvers.h>
24 #include <zorba/xquery_exception.h>
25
26
27 using namespace zorba;
28
29 /**
30 * Example to show the binding of external variables in the query context.
31 */
32 bool
context_example_1(Zorba * aZorba)33 context_example_1(Zorba* aZorba)
34 {
35 XQuery_t lQuery = aZorba->compileQuery("declare variable $var external; $var + $var");
36
37 ItemFactory* lFactory = aZorba->getItemFactory();
38
39 /* The item that is to be bound to the external variable */
40 Item lItem = lFactory->createInteger(4);
41
42 DynamicContext* lCtx = lQuery->getDynamicContext();
43
44 /* Actually perform the binding. */
45 lCtx->setVariable("var", lItem);
46
47 try {
48
49 std::cout << lQuery << std::endl;
50
51 } catch (ZorbaException &e) {
52 std::cerr << e << std::endl;
53 return false;
54 }
55
56 return true;
57 }
58
59 /**
60 * Example showing an erroneous query that defines an external variable, but
61 * whose dynamic context does not bind any values to it.
62 * One needs to use the setVariable() call defined on the dynamic context
63 * in order to use external variables correctly.
64 */
65 bool
context_example_2(Zorba * aZorba)66 context_example_2(Zorba* aZorba)
67 {
68 XQuery_t lQuery = aZorba->compileQuery("declare variable $var external; $var + $var");
69
70 try {
71
72 std::cout << lQuery << std::endl;
73
74 } catch (ZorbaException &e) {
75 std::cerr << e << std::endl;
76 return true;
77 }
78
79 return false;
80 }
81
82 /**
83 * Example to show the usage of the context item in a query. It is treated just as
84 * an external variable, except one uses the setContextItem() on the dynamic context
85 * to bind the value. It is an error to use a context item in a query but not bind it
86 * before execution.
87 */
88 bool
context_example_3(Zorba * aZorba)89 context_example_3(Zorba* aZorba)
90 {
91 XQuery_t lQuery = aZorba->compileQuery(".");
92
93 ItemFactory* lFactory = aZorba->getItemFactory();
94
95 Item lItem = lFactory->createInteger(4);
96
97 DynamicContext* lCtx = lQuery->getDynamicContext();
98
99 lCtx->setContextItem(lItem);
100
101 try {
102
103 std::cout << lQuery << std::endl;
104
105 } catch (ZorbaException &e) {
106 std::cerr << e << std::endl;
107 return false;
108 }
109
110 return true;
111 }
112
113
114 /**
115 * Example to show the use of document content as the value of an external variable.
116 */
117 bool
context_example_4(Zorba * aZorba)118 context_example_4(Zorba* aZorba)
119 {
120 std::ostringstream outStream1;
121 std::ostringstream outStream2;
122
123 std::auto_ptr<std::istream> lDocStream1(
124 new std::stringstream("<books><book>Book 1</book><book>Book 2</book></books>"));
125
126 std::auto_ptr<std::istream> lDocStream2(
127 new std::stringstream("<books><book>Book 1.1</book><book>Book 2.2</book></books>"));
128
129 try
130 {
131 XQuery_t lQuery = aZorba->compileQuery("declare variable $doc external; $doc//book[1]/text()");
132
133 DynamicContext* lCtx = lQuery->getDynamicContext();
134
135 // Parses the input stream and internally creates a datamodel instance
136 // that can be bound to the variable.
137 XmlDataManager* lXmlMgr = aZorba->getXmlDataManager();
138 Item lDoc = lXmlMgr->parseXML(*lDocStream1);
139
140 lCtx->setVariable("doc", lDoc);
141
142 outStream1 << lQuery << std::endl;
143 std::cout << outStream1.str() << std::endl;
144
145 // Reset the value of the $doc variable to the 2nd document.
146 lDoc = lXmlMgr->parseXML(*lDocStream2);
147 lCtx->setVariable("doc", lDoc);
148
149 outStream2 << lQuery << std::endl;
150 std::cout << outStream2.str() << std::endl;
151
152 #ifndef ZORBA_NO_ICU
153 if (outStream2.str() != "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\nBook 1.1\n")
154 #else
155 if (outStream2.str() != "<?xml version=\"1.0\"?>\nBook 1.1\n")
156 #endif /* ZORBA_NO_ICU */
157 {
158 std::cerr << "Test 4 failed with a wrong result : " << std::endl
159 << outStream2.str() << std::endl;
160 return false;
161 }
162 }
163 catch (ZorbaException& e)
164 {
165 std::cerr << "Test 4 failed with exception : " << e << std::endl;
166 return false;
167 }
168 catch (...)
169 {
170 std::cerr << "Test 4 failed with unknown exception" << std::endl;
171 return false;
172 }
173
174 return true;
175 }
176
177
178 /**
179 * Example to show the use of document content as the value of the context item in
180 * a query.
181 */
182 bool
context_example_5(Zorba * aZorba)183 context_example_5(Zorba* aZorba)
184 {
185
186 std::auto_ptr<std::istream> lDocStream(
187 new std::stringstream("<books><book>Book 1</book><book>Book 2</book></books>"));
188
189 XQuery_t lQuery = aZorba->compileQuery("declare variable $var external; .//book");
190
191 DynamicContext* lCtx = lQuery->getDynamicContext();
192 XmlDataManager* lXmlMgr = aZorba->getXmlDataManager();
193 Item lDoc = lXmlMgr->parseXML(*lDocStream);
194 lCtx->setContextItem(lDoc);
195
196 try {
197 std::cout << lQuery << std::endl;
198 } catch (ZorbaException& e) {
199 std::cerr << e << std::endl;
200 return false;
201 }
202 return true;
203 }
204
205 /**
206 * Example to show the use of collations in string comparison.
207 */
208 bool
context_example_6(Zorba * aZorba)209 context_example_6(Zorba* aZorba)
210 {
211 StaticContext_t lStaticContext = aZorba->createStaticContext();
212
213 /* Add the German collation to the context */
214 lStaticContext->addCollation("http://www.zorba-xquery.com/collations/PRIMARY/de/DE");
215
216 lStaticContext->setBaseURI("http://www.zorba-xquery.com/");
217
218 if ( lStaticContext->getBaseURI() != "http://www.zorba-xquery.com/")
219 return false;
220
221 /* Use the German collation as the third argument to the fn:compare() XQuery function */
222 XQuery_t lQuery = aZorba->compileQuery("fn:compare('Strasse', 'Stra??e', 'http://www.zorba-xquery.com/collations/PRIMARY/de/DE')",
223 lStaticContext);
224
225 try {
226
227 std::cout << lQuery << std::endl;
228
229 } catch (ZorbaException &e) {
230 std::cerr << e << std::endl;
231 return false;
232 }
233
234 return true;
235 }
236
237 /**
238 * Example to show the erroneous use of incorrect collation URIs in Zorba.
239 */
240 bool
context_example_7(Zorba * aZorba)241 context_example_7(Zorba* aZorba)
242 {
243 StaticContext_t lStaticContext = aZorba->createStaticContext();
244
245 try {
246 lStaticContext->addCollation("http://www.zorba-xquery.com/zorba/collations/PRIMARY");
247
248 XQuery_t lQuery = aZorba->compileQuery("fn:compare('Strasse', 'Stra??e', 'http://www.zorba-xquery.com/zorba/collations/PRIMARY')",
249 lStaticContext);
250
251 std::cout << lQuery << std::endl;
252
253 } catch (XQueryException &e) {
254 std::cerr << e << std::endl;
255 return true;
256 }
257
258 return false;
259 }
260
261 /**
262 * Example to show the connection between the ordering mode as defined in the query
263 * prolog and that in the context of the query.
264 */
265 bool
context_example_8(Zorba * aZorba)266 context_example_8(Zorba* aZorba)
267 {
268 /* The query sets the ordering mode to ordered */
269 XQuery_t lQuery1 = aZorba->compileQuery("declare ordering ordered; 1");
270
271 const StaticContext* lStaticContext1 = lQuery1->getStaticContext();
272
273 /* Programmatically the effect can be observed in the context */
274 if (lStaticContext1->getOrderingMode() != ordered)
275 return false;
276
277 XQuery_t lQuery2 = aZorba->compileQuery("declare ordering unordered; 1");
278
279 const StaticContext* lStaticContext2 = lQuery2->getStaticContext();
280
281 return (lStaticContext2->getOrderingMode() == unordered);
282 }
283
284 /**
285 * Example to show the ability to define the current dateTime in the dynamic context.
286 */
287 bool
context_example_9(Zorba * aZorba)288 context_example_9(Zorba* aZorba)
289 {
290 XQuery_t lQuery = aZorba->compileQuery("fn:hours-from-dateTime(fn:current-dateTime())");
291
292 DynamicContext* lDynContext = lQuery->getDynamicContext();
293
294 try {
295 Item lDateTimeItem = aZorba->getItemFactory()->createDateTime(2008, 03, 30, 16, 05, 42, 0);
296
297 lDynContext->setCurrentDateTime(lDateTimeItem);
298 std::cout << lQuery << std::endl;
299 }
300 catch (ZorbaException& e)
301 {
302 std::cerr << e << std::endl;
303 return false;
304 }
305
306 return true;
307 }
308
309 /**
310 * Example to show the findFunctions function of the static context
311 */
312 bool
context_example_10(Zorba * aZorba)313 context_example_10(Zorba* aZorba)
314 {
315 StaticContext_t lContext = aZorba->createStaticContext();
316
317 try
318 {
319 Item lQName = aZorba->getItemFactory()->createQName("http://www.w3.org/2005/xpath-functions", "doc");
320
321 std::vector<Function_t> lFunctions;
322 lContext->findFunctions(lQName, lFunctions);
323
324 std::cout << "Number of Functions " << lFunctions.size() << std::endl;
325
326 for (std::vector<Function_t>::const_iterator lIter = lFunctions.begin();
327 lIter != lFunctions.end(); ++lIter)
328 {
329 std::cout << "Function Name " << (*lIter)->getQName().getStringValue() << std::endl;
330 //std::cout << " requires dynamic context " << (*lIter)->requiresDynamicContext() << std::endl;
331 std::cout << " is updating " << (*lIter)->isUpdating() << std::endl;
332 std::cout << " arity " << (*lIter)->getArity() << std::endl;
333
334 lContext->disableFunction(*lIter);
335 }
336
337 try
338 {
339 XQuery_t lQuery = aZorba->compileQuery("fn:doc('test.xml')", lContext);
340 }
341 catch (ZorbaException const &se)
342 {
343 std::cerr << se << std::endl;
344 return true;
345 }
346 }
347 catch (ZorbaException &e)
348 {
349 std::cerr << e << std::endl;
350 return false;
351 }
352
353 return false;
354 }
355
356 static void
releaseStream(std::istream * aStream)357 releaseStream(std::istream* aStream)
358 {
359 delete aStream;
360 }
361
362 class PrologModuleURLResolver : public URLResolver
363 {
364 public:
~PrologModuleURLResolver()365 virtual ~PrologModuleURLResolver() {}
366
resolveURL(const String & aUrl,EntityData const * aEntityData)367 virtual Resource* resolveURL(
368 const String& aUrl,
369 EntityData const* aEntityData)
370 {
371 if (aEntityData->getKind() == EntityData::MODULE &&
372 aUrl == "http://www.zorba-xquery.com/mymodule")
373 {
374 // we have only one module
375 std::auto_ptr<std::stringstream> lQuery(new std::stringstream());
376 (*lQuery)
377 << "module namespace mymodule = 'http://www.zorba-xquery.com/mymodule';" << std::endl
378 << "import module namespace dml = 'http://www.zorba-xquery.com/modules/store/static/collections/dml';" << std::endl
379 << "declare namespace an = 'http://www.zorba-xquery.com/annotations';" << std::endl
380 << "declare variable $mymodule:var := 'myvar';" << std::endl
381 << "declare collection mymodule:collection;" << std::endl
382 << "declare %an:automatic %an:value-equality index mymodule:index" << std::endl
383 << " on nodes dml:collection(xs:QName('mymodule:collection'))" << std::endl
384 << " by ./foo as xs:string;" << std::endl;
385 return StreamResource::create(lQuery.release(), &releaseStream);
386 }
387 else {
388 return NULL;
389 }
390 }
391 };
392
393 /**
394 * test to demonstrate the loadProlog functionality that uses
395 * a query to populate a static context.
396 * The resulting context is used in order to compile another
397 * (main) query.
398 * The prolog contains a variable, a collection, and a function
399 * declaration.
400 */
401 bool
context_example_11(Zorba * aZorba)402 context_example_11(Zorba* aZorba)
403 {
404 StaticContext_t lContext = aZorba->createStaticContext();
405 PrologModuleURLResolver lResolver;
406 lContext->registerURLResolver(&lResolver);
407
408 try {
409 Zorba_CompilerHints_t hints;
410 std::stringstream lProlog;
411 lProlog << "import module namespace mymodule = 'http://www.zorba-xquery.com/mymodule';" << std::endl
412 << "import module namespace ddl = 'http://www.zorba-xquery.com/modules/store/static/collections/ddl';"
413 << std::endl
414 << "declare function local:collections() { " << std::endl
415 << " ddl:declared-collections()" << std::endl
416 << "};" << std::endl;
417 lContext->loadProlog(lProlog.str(), hints);
418
419 // compile the main query using the populated static context
420 XQuery_t lQuery = aZorba->compileQuery("$mymodule:var, local:collections()", lContext);
421
422 // execute the query and make sure that the result is correct
423 Zorba_SerializerOptions lSerOptions;
424 lSerOptions.omit_xml_declaration = ZORBA_OMIT_XML_DECLARATION_YES;
425 std::stringstream lResult;
426 lQuery->execute(lResult, &lSerOptions);
427 std::cout << "result " << lResult.str() << std::endl;
428
429 if (lResult.str().compare("myvar mymodule:collection") == 0) {
430 return true;
431 } else {
432 std::cerr << "result doesn't match expected result (myvar mymodule:collection)"
433 << std::endl;
434 return false;
435 }
436
437 } catch (XQueryException &e) {
438 std::cerr << e << std::endl;
439 return false;
440 }
441 return false;
442 }
443
444 bool
context_example_12(Zorba * aZorba)445 context_example_12(Zorba* aZorba)
446 {
447 std::ostringstream lTraceStream;
448
449 StaticContext_t lContext = aZorba->createStaticContext();
450
451 Item lTraceQName = aZorba->getItemFactory()->createQName("http://www.zorba-xquery.org/options", "trace");
452 lContext->declareOption(lTraceQName, "enable");
453 lContext->setTraceStream(lTraceStream);
454
455 try {
456 Zorba_CompilerHints_t hints;
457
458 XQuery_t aQuery = aZorba->compileQuery("fn:trace(1 to 3, 'foo')", lContext);
459
460 // execute the query
461 std::cout << aQuery << std::endl;
462
463 // check if the trace was successful
464 std::string lTraceString = lTraceStream.str();
465 std::cout << lTraceString << std::endl;
466 if (lTraceString.compare("foo [1]: 1\n"
467 "foo [2]: 2\n"
468 "foo [3]: 3\n") != 0) {
469 return false;
470 }
471 std::cout << lTraceString << std::endl;
472 return true;
473
474 } catch (XQueryException &e) {
475 std::cerr << e << std::endl;
476 return false;
477 }
478
479 return false;
480 }
481
482 struct callback_data
483 {
484 bool b;
485 };
486
487 int
context(int argc,char * argv[])488 context(int argc, char* argv[])
489 {
490 void* lStore = zorba::StoreManager::getStore();
491
492 Zorba* lZorba = Zorba::getInstance(lStore);
493 bool res = false;
494
495 std::cout << "executing example 1" << std::endl;
496 res = context_example_1(lZorba);
497 if (!res) return 1;
498 std::cout << std::endl;
499
500 std::cout << "executing example 2" << std::endl;
501 res = context_example_2(lZorba);
502 if (!res) return 1;
503 std::cout << std::endl;
504
505 std::cout << "executing example 3" << std::endl;
506 res = context_example_3(lZorba);
507 if (!res) return 1;
508 std::cout << std::endl;
509
510 std::cout << "executing example 4" << std::endl;
511 res = context_example_4(lZorba);
512 if (!res) return 1;
513 std::cout << std::endl;
514
515 std::cout << "executing example 5" << std::endl;
516 res = context_example_5(lZorba);
517 if (!res) return 1;
518 std::cout << std::endl;
519
520 std::cout << "executing example 6" << std::endl;
521 res = context_example_6(lZorba);
522 if (!res) return 1;
523 std::cout << std::endl;
524
525 std::cout << "executing example 7" << std::endl;
526 res = context_example_7(lZorba);
527 if (!res) return 1;
528 std::cout << std::endl;
529
530 std::cout << "executing example_8" << std::endl;
531 res = context_example_8(lZorba);
532 if (!res) return 1;
533 std::cout << std::endl;
534
535 std::cout << "executing example_9" << std::endl;
536 res = context_example_9(lZorba);
537 if (!res) return 1;
538 std::cout << std::endl;
539
540 std::cout << "executing example_10" << std::endl;
541 res = context_example_10(lZorba);
542 if (!res) return 1;
543 std::cout << std::endl;
544
545 std::cout << "executing example_11" << std::endl;
546 res = context_example_11(lZorba);
547 if (!res) return 1;
548 std::cout << std::endl;
549
550 std::cout << "executing example_12" << std::endl;
551 res = context_example_12(lZorba);
552 if (!res) return 1;
553 std::cout << std::endl;
554
555 lZorba->shutdown();
556 zorba::StoreManager::shutdownStore(lStore);
557 return 0;
558 }
559