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