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 #include "stdafx.h"
17
18 #include "diagnostics/xquery_diagnostics.h"
19 #include "diagnostics/assert.h"
20 #include "diagnostics/dict.h"
21 #include "diagnostics/util_macros.h"
22
23 #include "zorbatypes/datetime.h"
24 #include "zorbatypes/duration.h"
25
26 #include "system/globalenv.h"
27
28 #include "context/dynamic_context.h"
29 #include "context/static_context.h"
30
31 #include "types/root_typemanager.h"
32 #include "types/typeops.h"
33 #include "types/casting.h"
34
35 #include "compiler/parser/query_loc.h"
36 #include "compiler/api/compilercb.h"
37
38 #include "runtime/core/arithmetic_impl.h"
39 #include "runtime/numerics/NumericsImpl.h"
40 #include "runtime/visitors/planiter_visitor.h"
41
42 #include "store/api/item_factory.h"
43
44 namespace zorba {
45
46 SERIALIZABLE_TEMPLATE_INSTANCE(GenericArithIterator,
47 GenericArithIterator<AddOperation>,
48 1)
49
50 SERIALIZABLE_TEMPLATE_INSTANCE(GenericArithIterator,
51 GenericArithIterator<SubtractOperation>,
52 2)
53
54 SERIALIZABLE_TEMPLATE_INSTANCE(GenericArithIterator,
55 GenericArithIterator<MultiplyOperation>,
56 3)
57
58 SERIALIZABLE_TEMPLATE_INSTANCE(GenericArithIterator,
59 GenericArithIterator<DivideOperation>,
60 4)
61
62 SERIALIZABLE_TEMPLATE_INSTANCE(GenericArithIterator,
63 GenericArithIterator<IntegerDivideOperation>,
64 5)
65
66 SERIALIZABLE_TEMPLATE_INSTANCE(GenericArithIterator,
67 GenericArithIterator<ModOperation>,
68 6)
69
createError(const TypeManager * tm,const char * aOp,const QueryLoc * aLoc,store::SchemaTypeCode aType0,store::SchemaTypeCode aType1)70 void ArithOperationsCommons::createError(
71 const TypeManager* tm,
72 const char* aOp,
73 const QueryLoc* aLoc,
74 store::SchemaTypeCode aType0,
75 store::SchemaTypeCode aType1)
76 {
77 xqtref_t t0 = tm->create_builtin_atomic_type(aType0,TypeConstants::QUANT_ONE);
78 xqtref_t t1 = tm->create_builtin_atomic_type(aType1,TypeConstants::QUANT_ONE);
79
80 RAISE_ERROR(err::XPTY0004, aLoc,
81 ERROR_PARAMS(ZED(OperationNotPossibleWithTypes_234), aOp, *t0, *t1 ));
82 }
83
84
85
86 /*******************************************************************************
87 GenericArithIterator
88 ********************************************************************************/
89
90 template< class Operations>
GenericArithIterator(static_context * sctx,const QueryLoc & loc,PlanIter_t & iter0,PlanIter_t & iter1)91 GenericArithIterator<Operations>::GenericArithIterator(
92 static_context* sctx,
93 const QueryLoc& loc,
94 PlanIter_t& iter0,
95 PlanIter_t& iter1)
96 :
97 BinaryBaseIterator<GenericArithIterator<Operations>, PlanIteratorState >(sctx, loc, iter0, iter1)
98 {
99 }
100
101
102 template < class Operation >
nextImpl(store::Item_t & result,PlanState & planState) const103 bool GenericArithIterator<Operation>::nextImpl(
104 store::Item_t& result,
105 PlanState& planState) const
106 {
107 store::Item_t n0;
108 store::Item_t n1;
109 bool status;
110
111 PlanIteratorState* state;
112 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
113
114 if (this->consumeNext(n0, this->theChild0.getp(), planState))
115 {
116 if (this->consumeNext(n1, this->theChild1.getp(), planState))
117 {
118 if (n0->getTypeCode() != store::JS_NULL &&
119 n1->getTypeCode() != store::JS_NULL)
120 {
121 status = compute(result,
122 planState.theLocalDynCtx,
123 this->theSctx->get_typemanager(),
124 this->loc,
125 n0,
126 n1);
127 /*
128 if (this->consumeNext(n0, this->theChild0.getp(), planState) ||
129 this->consumeNext(n1, this->theChild1.getp(), planState))
130 {
131 throw XQUERY_EXCEPTION(
132 err::XPTY0004,
133 ERROR_PARAMS( ZED( NoSeqAsArithOp ) ),
134 ERROR_LOC( this->loc )
135 );
136 }
137 */
138 STACK_PUSH ( status, state );
139 }
140 }
141 }
142
143 STACK_END (state);
144 }
145
146
147 template <class Operation>
accept(PlanIterVisitor & v) const148 void GenericArithIterator<Operation>::accept(PlanIterVisitor& v) const
149 {
150 v.beginVisit(*this);
151
152 this->theChild0->accept(v);
153 this->theChild1->accept(v);
154
155 v.endVisit(*this);
156 }
157
158
159 template < class Operation >
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc & aLoc,store::Item_t & n0,store::Item_t & n1)160 bool GenericArithIterator<Operation>::compute(
161 store::Item_t& result,
162 dynamic_context* dctx,
163 const TypeManager* tm,
164 const QueryLoc& aLoc,
165 store::Item_t& n0,
166 store::Item_t& n1)
167 {
168 RootTypeManager& rtm = GENV_TYPESYSTEM;
169
170 assert(n0->isAtomic());
171 assert(n1->isAtomic());
172
173 xqtref_t type0 = tm->create_value_type(n0);
174 xqtref_t type1 = tm->create_value_type(n1);
175
176 if (TypeOps::is_numeric(tm, *type0) &&
177 (TypeOps::is_subtype(tm, *type1, *rtm.YM_DURATION_TYPE_ONE) ||
178 TypeOps::is_subtype(tm, *type1, *rtm.DT_DURATION_TYPE_ONE)))
179 {
180 GenericCast::castToAtomic(n0, n0, &*rtm.DOUBLE_TYPE_ONE, tm, NULL, aLoc);
181
182 if (TypeOps::is_subtype(tm, *type1, *rtm.YM_DURATION_TYPE_ONE))
183 {
184 return Operation::template
185 compute<store::XS_DOUBLE, store::XS_YM_DURATION>
186 (result, dctx, tm, &aLoc, n0, n1);
187 }
188 else
189 {
190 return Operation::template
191 compute<store::XS_DOUBLE,store::XS_DT_DURATION>
192 (result, dctx, tm, &aLoc, n0, n1);
193 }
194 }
195 else if (TypeOps::is_subtype(tm, *type0, *rtm.DT_DURATION_TYPE_ONE) &&
196 TypeOps::is_subtype(tm, *type1, *rtm.TIME_TYPE_ONE))
197 {
198 return Operation::template
199 compute<store::XS_DURATION,store::XS_TIME>
200 (result, dctx, tm, &aLoc, n0, n1);
201 }
202 else if (TypeOps::is_subtype(tm, *type0, *rtm.YM_DURATION_TYPE_ONE))
203 {
204 if(TypeOps::is_numeric(tm, *type1))
205 {
206 GenericCast::castToAtomic(n1, n1, &*rtm.DOUBLE_TYPE_ONE, tm, NULL, aLoc);
207 return Operation::template
208 compute<store::XS_YM_DURATION,store::XS_DOUBLE>
209 (result, dctx, tm, &aLoc, n0, n1);
210 }
211 else if (TypeOps::is_subtype(tm, *type1, *rtm.DATETIME_TYPE_ONE))
212 {
213 return Operation::template
214 compute<store::XS_DURATION,store::XS_DATETIME>
215 (result, dctx, tm, &aLoc, n0, n1);
216 }
217 else if (TypeOps::is_subtype(tm, *type1, *rtm.DATE_TYPE_ONE))
218 {
219 return Operation::template
220 compute<store::XS_DURATION,store::XS_DATE>
221 (result, dctx, tm, &aLoc, n0, n1);
222 }
223 else if (TypeOps::is_equal(tm, *type0, *type1))
224 {
225 return Operation::template
226 computeSingleType<store::XS_YM_DURATION>
227 (result, dctx, tm, &aLoc, n0, n1);
228 }
229 }
230 else if (TypeOps::is_subtype(tm, *type0, *rtm.DT_DURATION_TYPE_ONE))
231 {
232 if(TypeOps::is_numeric(tm, *type1))
233 {
234 GenericCast::castToAtomic(n1, n1, &*rtm.DOUBLE_TYPE_ONE, tm, NULL, aLoc);
235
236 return Operation::template
237 compute<store::XS_DT_DURATION,store::XS_DOUBLE>
238 (result, dctx, tm, &aLoc, n0, n1);
239 }
240 else if (TypeOps::is_subtype(tm, *type1, *rtm.DATETIME_TYPE_ONE))
241 {
242 return Operation::template
243 compute<store::XS_DURATION,store::XS_DATETIME>
244 (result, dctx, tm, &aLoc, n0, n1);
245 }
246 else if (TypeOps::is_subtype(tm, *type1, *rtm.DATE_TYPE_ONE))
247 {
248 return Operation::template
249 compute<store::XS_DURATION,store::XS_DATE>
250 (result, dctx, tm, &aLoc, n0, n1);
251 }
252 else if (TypeOps::is_equal(tm, *type0, *type1))
253 {
254 return Operation::template
255 computeSingleType<store::XS_DT_DURATION>
256 (result, dctx, tm, &aLoc, n0, n1);
257 }
258 }
259 else if(TypeOps::is_subtype(tm, *type0, *rtm.DATETIME_TYPE_ONE))
260 {
261 if(TypeOps::is_subtype(tm, *type1, *rtm.DATETIME_TYPE_ONE))
262 {
263 return Operation::template
264 compute<store::XS_DATETIME,store::XS_DATETIME>
265 (result, dctx, tm, &aLoc, n0, n1);
266 }
267 else if (TypeOps::is_subtype(tm, *type1, *rtm.DURATION_TYPE_ONE ))
268 {
269 return Operation::template
270 compute<store::XS_DATETIME,store::XS_DURATION>
271 (result, dctx, tm, &aLoc, n0, n1);
272 }
273 }
274 else if(TypeOps::is_subtype(tm, *type0, *rtm.DATE_TYPE_ONE))
275 {
276 if (TypeOps::is_subtype(tm, *type1, *rtm.DATE_TYPE_ONE))
277 {
278 return Operation::template
279 compute<store::XS_DATE,store::XS_DATE>
280 (result, dctx, tm, &aLoc, n0, n1);
281 }
282 else if (TypeOps::is_subtype(tm, *type1, *rtm.DURATION_TYPE_ONE))
283 {
284 return Operation::template
285 compute<store::XS_DATE,store::XS_DURATION>
286 (result, dctx, tm, &aLoc, n0, n1);
287 }
288 }
289 else if(TypeOps::is_subtype(tm, *type0, *rtm.TIME_TYPE_ONE))
290 {
291 if(TypeOps::is_subtype(tm, *type1, *rtm.TIME_TYPE_ONE))
292 {
293 return Operation::template
294 compute<store::XS_TIME,store::XS_TIME>
295 (result, dctx, tm, &aLoc, n0, n1);
296 }
297 else if (TypeOps::is_subtype(tm, *type1, *rtm.DT_DURATION_TYPE_ONE))
298 {
299 return Operation::template
300 compute<store::XS_TIME,store::XS_DURATION>
301 (result, dctx, tm, &aLoc, n0, n1);
302 }
303 }
304 else if ((TypeOps::is_numeric(tm, *type0) ||
305 TypeOps::is_subtype(tm, *type0, *rtm.UNTYPED_ATOMIC_TYPE_ONE)) &&
306 ( TypeOps::is_numeric(tm, *type1) ||
307 TypeOps::is_subtype(tm, *type1, *rtm.UNTYPED_ATOMIC_TYPE_ONE)))
308 {
309 return NumArithIterator<Operation>::
310 computeAtomic(result, dctx, tm, aLoc, n0, type0, n1, type1);
311 }
312
313
314 RAISE_ERROR(err::XPTY0004, aLoc,
315 ERROR_PARAMS(ZED(ArithOpNotDefinedBetween_23), *type0, *type1));
316
317 return false; // suppresses wanring
318 }
319
320
321 /*******************************************************************************
322 AddOperation
323 ********************************************************************************/
324
325 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)326 bool AddOperation::compute<store::XS_YM_DURATION,store::XS_YM_DURATION>
327 ( store::Item_t& result,
328 dynamic_context* dctx,
329 const TypeManager* tm,
330 const QueryLoc* loc,
331 const store::Item* i0,
332 const store::Item* i1 )
333 {
334 std::auto_ptr<Duration> d(i0->getYearMonthDurationValue() + i1->getYearMonthDurationValue());
335 return GENV_ITEMFACTORY->createYearMonthDuration(result, d.get());
336 }
337
338
339 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)340 bool AddOperation::compute<store::XS_DT_DURATION,store::XS_DT_DURATION>
341 ( store::Item_t& result,
342 dynamic_context* dctx,
343 const TypeManager* tm,
344 const QueryLoc* loc,
345 const store::Item* i0,
346 const store::Item* i1 )
347 {
348 std::auto_ptr<Duration> d(i0->getDayTimeDurationValue() + i1->getDayTimeDurationValue());
349 return GENV_ITEMFACTORY->createDayTimeDuration(result, d.get());
350 }
351
352
353 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)354 bool AddOperation::compute<store::XS_DATETIME,store::XS_DURATION>(
355 store::Item_t& result,
356 dynamic_context* dctx,
357 const TypeManager* tm,
358 const QueryLoc* loc,
359 const store::Item* i0,
360 const store::Item* i1)
361 {
362 std::auto_ptr<xs_dateTime> d(i0->getDateTimeValue().addDuration(i1->getDurationValue()));
363 return GENV_ITEMFACTORY->createDateTime(result, d.get());
364 }
365
366
367 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)368 bool AddOperation::compute<store::XS_DURATION,store::XS_DATETIME>(
369 store::Item_t& result,
370 dynamic_context* dctx,
371 const TypeManager* tm,
372 const QueryLoc* loc,
373 const store::Item* i0,
374 const store::Item* i1)
375 {
376 std::auto_ptr<xs_dateTime> d(i1->getDateTimeValue().addDuration(i0->getDurationValue()));
377 return GENV_ITEMFACTORY->createDateTime(result, d.get());
378 }
379
380
381 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)382 bool AddOperation::compute<store::XS_DATE,store::XS_DURATION>
383 ( store::Item_t& result,
384 dynamic_context* dctx,
385 const TypeManager* tm,
386 const QueryLoc* loc,
387 const store::Item* i0,
388 const store::Item* i1)
389 {
390 std::auto_ptr<xs_date> d(i0->getDateValue().addDuration(i1->getDurationValue()));
391 return GENV_ITEMFACTORY->createDate(result, d.get());
392 }
393
394
395 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)396 bool AddOperation::compute<store::XS_DURATION,store::XS_DATE>
397 ( store::Item_t& result,
398 dynamic_context* dctx,
399 const TypeManager* tm,
400 const QueryLoc* loc,
401 const store::Item* i0,
402 const store::Item* i1 )
403 {
404 std::auto_ptr<xs_date> d(i1->getDateValue().addDuration(i0->getDurationValue()));
405 return GENV_ITEMFACTORY->createDate (result, d.get());
406 }
407
408
409 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)410 bool AddOperation::compute<store::XS_TIME,store::XS_DURATION>
411 ( store::Item_t& result,
412 dynamic_context* dctx,
413 const TypeManager* tm,
414 const QueryLoc* loc,
415 const store::Item* i0,
416 const store::Item* i1 )
417 {
418 std::auto_ptr<xs_time> t(i0->getTimeValue().addDuration(i1->getDurationValue()));
419 return GENV_ITEMFACTORY->createTime (result, t.get());
420 }
421
422
423 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)424 bool AddOperation::compute<store::XS_DURATION,store::XS_TIME>
425 ( store::Item_t& result,
426 dynamic_context* dctx,
427 const TypeManager* tm,
428 const QueryLoc* loc,
429 const store::Item* i0,
430 const store::Item* i1 )
431 {
432 std::auto_ptr<xs_time> t(i1->getTimeValue().addDuration(i0->getDurationValue()));
433 return GENV_ITEMFACTORY->createTime (result, t.get());
434 }
435
436
437 /*******************************************************************************
438 SubtractOperation
439 ********************************************************************************/
440
441 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)442 bool SubtractOperation::compute<store::XS_YM_DURATION,store::XS_YM_DURATION>(
443 store::Item_t& result,
444 dynamic_context* dctx,
445 const TypeManager* tm,
446 const QueryLoc* loc,
447 const store::Item* i0,
448 const store::Item* i1 )
449 {
450 std::auto_ptr<Duration> d(i0->getYearMonthDurationValue() -
451 i1->getYearMonthDurationValue());
452
453 return GENV_ITEMFACTORY->createYearMonthDuration(result, d.get());
454 }
455
456
457 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)458 bool SubtractOperation::compute<store::XS_DT_DURATION,store::XS_DT_DURATION>(
459 store::Item_t& result,
460 dynamic_context* dctx,
461 const TypeManager* tm,
462 const QueryLoc* loc,
463 const store::Item* i0,
464 const store::Item* i1)
465 {
466 std::auto_ptr<Duration> d(i0->getDayTimeDurationValue() -
467 i1->getDayTimeDurationValue());
468
469 return GENV_ITEMFACTORY->createDayTimeDuration(result, d.get());
470 }
471
472
473 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)474 bool SubtractOperation::compute<store::XS_DATETIME,store::XS_DURATION>(
475 store::Item_t& result,
476 dynamic_context* dctx,
477 const TypeManager* tm,
478 const QueryLoc* loc,
479 const store::Item* i0,
480 const store::Item* i1)
481 {
482 std::auto_ptr<xs_dateTime> d(i0->getDateTimeValue().subtractDuration(i1->getDurationValue()));
483 return GENV_ITEMFACTORY->createDateTime(result, d.get());
484 }
485
486
487 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)488 bool SubtractOperation::compute<store::XS_DATE,store::XS_DURATION>(
489 store::Item_t& result,
490 dynamic_context* dctx,
491 const TypeManager* tm,
492 const QueryLoc* loc,
493 const store::Item* i0,
494 const store::Item* i1)
495 {
496 std::auto_ptr<xs_date> d(i0->getDateValue().subtractDuration(i1->getDurationValue()));
497 return GENV_ITEMFACTORY->createDate(result, d.get());
498 }
499
500
501 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)502 bool SubtractOperation::compute<store::XS_TIME,store::XS_DURATION>(
503 store::Item_t& result,
504 dynamic_context* dctx,
505 const TypeManager* tm,
506 const QueryLoc* loc,
507 const store::Item* i0,
508 const store::Item* i1)
509 {
510 std::auto_ptr<xs_time> t(i0->getTimeValue().subtractDuration(i1->getDurationValue()));
511 return GENV_ITEMFACTORY->createTime(result, t.get());
512 }
513
514
515 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)516 bool SubtractOperation::compute<store::XS_DATETIME,store::XS_DATETIME>(
517 store::Item_t& result,
518 dynamic_context* dctx,
519 const TypeManager* tm,
520 const QueryLoc* loc,
521 const store::Item* i0,
522 const store::Item* i1)
523 {
524 std::auto_ptr<Duration> d;
525 try
526 {
527 d.reset(i0->getDateTimeValue().subtractDateTime(&i1->getDateTimeValue(),
528 dctx->get_implicit_timezone()));
529 }
530 catch (InvalidTimezoneException const&)
531 {
532 throw XQUERY_EXCEPTION(err::FODT0003);
533 }
534 return GENV_ITEMFACTORY->createDayTimeDuration(result, d.get());
535 }
536
537
538 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)539 bool SubtractOperation::compute<store::XS_DATE,store::XS_DATE>(
540 store::Item_t& result,
541 dynamic_context* dctx,
542 const TypeManager* tm,
543 const QueryLoc* loc,
544 const store::Item* i0,
545 const store::Item* i1)
546 {
547 std::auto_ptr<Duration> d;
548 try
549 {
550 d.reset(i0->getTimeValue().subtractDateTime(&i1->getTimeValue(),
551 dctx->get_implicit_timezone()));
552 }
553 catch (InvalidTimezoneException const&)
554 {
555 throw XQUERY_EXCEPTION(err::FODT0003);
556 }
557 return GENV_ITEMFACTORY->createDayTimeDuration(result, d.get());
558 }
559
560
561 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)562 bool SubtractOperation::compute<store::XS_TIME,store::XS_TIME>(
563 store::Item_t& result,
564 dynamic_context* dctx,
565 const TypeManager* tm,
566 const QueryLoc* loc,
567 const store::Item* i0,
568 const store::Item* i1)
569 {
570 std::auto_ptr<Duration> d;
571 try
572 {
573 d.reset(i0->getTimeValue().subtractDateTime(&i1->getTimeValue(),
574 dctx->get_implicit_timezone()));
575 }
576 catch (InvalidTimezoneException const&)
577 {
578 throw XQUERY_EXCEPTION(err::FODT0003);
579 }
580 return GENV_ITEMFACTORY->createDayTimeDuration(result, d.get());
581 }
582
583
584 /*******************************************************************************
585 MultiplyOperation
586 ********************************************************************************/
587
588 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)589 bool MultiplyOperation::compute<store::XS_YM_DURATION,store::XS_DOUBLE>(
590 store::Item_t& result,
591 dynamic_context* dctx,
592 const TypeManager* tm,
593 const QueryLoc* loc,
594 const store::Item* i0,
595 const store::Item* i1)
596 {
597 std::auto_ptr<Duration> d;
598
599 if ( i1->getDoubleValue().isPosInf() || i1->getDoubleValue().isNegInf() )
600 throw XQUERY_EXCEPTION( err::FODT0002, ERROR_LOC( loc ) );
601 else if (i1->getDoubleValue().isNaN())
602 throw XQUERY_EXCEPTION( err::FOCA0005, ERROR_LOC( loc ) );
603 else
604 d.reset(i0->getYearMonthDurationValue() * (i1->getDoubleValue()));
605
606 return GENV_ITEMFACTORY->createYearMonthDuration(result, d.get());
607 }
608
609
610 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)611 bool MultiplyOperation::compute<store::XS_DT_DURATION,store::XS_DOUBLE>(
612 store::Item_t& result,
613 dynamic_context* dctx,
614 const TypeManager* tm,
615 const QueryLoc* loc,
616 const store::Item* i0,
617 const store::Item* i1)
618 {
619 std::auto_ptr<Duration> d;
620
621 if ( i1->getDoubleValue().isPosInf() || i1->getDoubleValue().isNegInf() )
622 throw XQUERY_EXCEPTION( err::FODT0002, ERROR_LOC( loc ) );
623 else if (i1->getDoubleValue().isNaN())
624 throw XQUERY_EXCEPTION( err::FOCA0005, ERROR_LOC( loc ) );
625 else
626 d.reset(i0->getDayTimeDurationValue() * (i1->getDoubleValue()));
627
628 return GENV_ITEMFACTORY->createDayTimeDuration(result, d.get());
629 }
630
631
632 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)633 bool MultiplyOperation::compute<store::XS_DOUBLE,store::XS_YM_DURATION>(
634 store::Item_t& result,
635 dynamic_context* dctx,
636 const TypeManager* tm,
637 const QueryLoc* loc,
638 const store::Item* i0,
639 const store::Item* i1)
640 {
641 return MultiplyOperation::compute<store::XS_YM_DURATION,store::XS_DOUBLE>(result, dctx, tm, loc, i1, i0);
642 }
643
644
645 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)646 bool MultiplyOperation::compute<store::XS_DOUBLE,store::XS_DT_DURATION>
647 ( store::Item_t& result,
648 dynamic_context* dctx,
649 const TypeManager* tm,
650 const QueryLoc* loc,
651 const store::Item* i0,
652 const store::Item* i1 )
653 {
654 return MultiplyOperation::compute<store::XS_DT_DURATION,store::XS_DOUBLE>(result, dctx, tm, loc, i1, i0);
655 }
656
657
658 /*******************************************************************************
659 DivideOperation
660 ********************************************************************************/
661
662 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)663 bool DivideOperation::compute<store::XS_YM_DURATION,store::XS_DOUBLE>(
664 store::Item_t& result,
665 dynamic_context* dctx,
666 const TypeManager* tm,
667 const QueryLoc* loc,
668 const store::Item* i0,
669 const store::Item* i1)
670 {
671 std::auto_ptr<Duration> d;
672
673 if( i1->getDoubleValue().isPosInf() || i1->getDoubleValue().isNegInf() )
674 {
675 d = std::auto_ptr<Duration>(new Duration(Duration::YEARMONTHDURATION_FACET));
676 }
677 else if ( i1->getDoubleValue().isZero() )
678 throw XQUERY_EXCEPTION( err::FODT0002, ERROR_LOC( loc ) );
679 else if ( i1->getDoubleValue().isNaN() )
680 throw XQUERY_EXCEPTION( err::FOCA0005, ERROR_LOC( loc ) );
681 else
682 d = std::auto_ptr<Duration>(i0->getYearMonthDurationValue() / i1->getDoubleValue());
683
684 return GENV_ITEMFACTORY->createYearMonthDuration(result, d.get());
685 }
686
687
688 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)689 bool DivideOperation::compute<store::XS_DT_DURATION,store::XS_DOUBLE>
690 ( store::Item_t& result,
691 dynamic_context* dctx,
692 const TypeManager* tm,
693 const QueryLoc* loc,
694 const store::Item* i0,
695 const store::Item* i1 )
696 {
697 std::auto_ptr<Duration> d;
698
699 if( i1->getDoubleValue().isPosInf() || i1->getDoubleValue().isNegInf() )
700 {
701 d.reset(new Duration());
702 }
703 else if ( i1->getDoubleValue().isZero() )
704 throw XQUERY_EXCEPTION( err::FODT0002, ERROR_LOC( loc ) );
705 else if ( i1->getDoubleValue().isNaN() )
706 throw XQUERY_EXCEPTION( err::FOCA0005, ERROR_LOC( loc ) );
707 else
708 d.reset(i0->getDayTimeDurationValue() / i1->getDoubleValue());
709
710 return GENV_ITEMFACTORY->createDayTimeDuration(result, d.get());
711 }
712
713
714 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)715 bool DivideOperation::compute<store::XS_YM_DURATION, store::XS_YM_DURATION>
716 ( store::Item_t& result,
717 dynamic_context* dctx,
718 const TypeManager* tm,
719 const QueryLoc* loc,
720 const store::Item* i0,
721 const store::Item* i1 )
722 {
723 xs_decimal d = i0->getYearMonthDurationValue() / i1->getYearMonthDurationValue();
724 return GENV_ITEMFACTORY->createDecimal(result, d);
725 }
726
727
728 template<>
compute(store::Item_t & result,dynamic_context * dctx,const TypeManager * tm,const QueryLoc * loc,const store::Item * i0,const store::Item * i1)729 bool DivideOperation::compute<store::XS_DT_DURATION, store::XS_DT_DURATION>(
730 store::Item_t& result,
731 dynamic_context* dctx,
732 const TypeManager* tm,
733 const QueryLoc* loc,
734 const store::Item* i0,
735 const store::Item* i1 )
736 {
737 xs_decimal d = i0->getDayTimeDurationValue() / i1->getDayTimeDurationValue();
738
739 return GENV_ITEMFACTORY->createDecimal(result, d);
740 }
741
742
743
744 /*******************************************************************************
745 instantiate GenericArithIterator for all kinds of arithmetic operators
746 ********************************************************************************/
747 template class GenericArithIterator<AddOperation>;
748 template class GenericArithIterator<SubtractOperation>;
749 template class GenericArithIterator<MultiplyOperation>;
750 template class GenericArithIterator<DivideOperation>;
751 template class GenericArithIterator<IntegerDivideOperation>;
752 template class GenericArithIterator<ModOperation>;
753
754 } // namespace zorba
755 /* vim:set et sw=2 ts=2: */
756