~zorba-coders/zorba/bug-950621

« back to all changes in this revision

Viewing changes to src/functions/BooleanImpl.cpp

  • Committer: brantmat at ETHZ
  • Date: 2007-10-09 12:58:38 UTC
  • Revision ID: svn-v4:8046edc3-af21-0410-8661-ec7318497eea:trunk/zorba:904
commit of the new directory structure

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *      Copyright 2006-2007 FLWOR Foundation.
 
3
 *  Authors: Tim Kraska, David Graf
 
4
 */
 
5
 
 
6
#include "BooleanImpl.h"
 
7
#include "../types/casting.h"
 
8
#include "../runtime/zorba.h"
 
9
#include "../errors/Error.h"
 
10
#include "../functions/AccessorsImpl.h"
 
11
#include "../store/api/temp_seq.h"
 
12
 
 
13
namespace xqp
 
14
{
 
15
 
 
16
        /*______________________________________________________________________
 
17
        |
 
18
        |       15.1.1 fn:boolean
 
19
        |       fn:boolean($arg as item()*) as xs:boolean
 
20
        |
 
21
        |       Computes the effective boolean value of the sequence $arg.
 
22
        |_______________________________________________________________________*/
 
23
        FnBooleanIterator::FnBooleanIterator ( const yy::location& loc, Iterator_t& arg0, bool negate_arg )
 
24
        :
 
25
                Batcher<FnBooleanIterator> ( loc ), arg0_ ( arg0 ), negate ( negate_arg ) {}
 
26
                
 
27
        FnBooleanIterator::~FnBooleanIterator() {}
 
28
                        
 
29
        std::ostream&
 
30
        FnBooleanIterator::_show ( std::ostream& os ) const
 
31
        {
 
32
                this->arg0_->show ( os );
 
33
                return os;
 
34
        }
 
35
 
 
36
        Item_t
 
37
        FnBooleanIterator::effectiveBooleanValue ( const yy::location& loc, IteratorTreeStateBlock& stateBlock, Iterator_t& iter, bool negate )
 
38
        {
 
39
                Item_t item;
 
40
                TypeCode type;
 
41
                Item_t result;
 
42
 
 
43
                // TODO produceNext must be replaced to allow batching
 
44
                item = iter->produceNext(stateBlock);
 
45
 
 
46
                if ( item == NULL )
 
47
                {
 
48
                        // empty sequence => false
 
49
                        result = zorba::getZorbaForCurrentThread()->getItemFactory()->createBoolean ( negate ^ false );
 
50
                }
 
51
                else if ( item->isNode() )
 
52
                {
 
53
                        // node => true
 
54
                        result = zorba::getZorbaForCurrentThread()->getItemFactory()->createBoolean ( negate ^ true );
 
55
                }
 
56
                else
 
57
                {
 
58
                        type = item->getType();
 
59
                        if (
 
60
                                        // TODO produceNext must be replaced to allow batching
 
61
                            ( iter->produceNext(stateBlock) == NULL )
 
62
                            &&
 
63
                            ( type == xs_boolean
 
64
                              || sequence_type::derives_from ( type, xs_string )
 
65
                              || sequence_type::derives_from ( type, xs_anyURI )
 
66
                              || sequence_type::derives_from ( type, xs_untypedAtomicValue )
 
67
                              || sequence_type::isNumeric ( type )
 
68
                            )
 
69
                        )
 
70
                        {
 
71
                                // atomic type xs_boolean, xs_string, xs_anyURI, xs_untypedAtomic
 
72
                                // => effective boolean value is defined in the items
 
73
                                result = item->getEBV();
 
74
                                if (negate)
 
75
                                        result = zorba::getZorbaForCurrentThread()->getItemFactory()->createBoolean ( negate ^ result->getBooleanValue() );
 
76
                        }
 
77
                        else
 
78
                        {
 
79
                                // else error => fn:boolean not defined
 
80
                                ZorbaErrorAlerts::error_alert (
 
81
                                    error_messages::FORG0006_INVALID_ARGUMENT_TYPE,
 
82
                                    error_messages::RUNTIME_ERROR,
 
83
                                    &loc,
 
84
                                    false,
 
85
                                    "Wrong arguments in fn:boolean function!"
 
86
                                );
 
87
                        }
 
88
                }
 
89
 
 
90
                return result;
 
91
        }
 
92
 
 
93
        Item_t
 
94
        FnBooleanIterator::nextImpl(IteratorTreeStateBlock& stateBlock)
 
95
        {       
 
96
                STACK_INIT();
 
97
                STACK_PUSH ( FnBooleanIterator::effectiveBooleanValue ( this->loc, stateBlock, this->arg0_, this->negate ) );
 
98
                STACK_END();
 
99
        }
 
100
 
 
101
        void
 
102
        FnBooleanIterator::resetImpl(IteratorTreeStateBlock& stateBlock)
 
103
        {
 
104
                this->resetChild ( this->arg0_, stateBlock );
 
105
        }
 
106
 
 
107
        void
 
108
        FnBooleanIterator::releaseResourcesImpl(IteratorTreeStateBlock& stateBlock)
 
109
        {
 
110
                this->releaseChildResources ( this->arg0_, stateBlock);
 
111
        }
 
112
        /* end class FnBooleanIterator */
 
113
        
 
114
        /* begin class LogicIterator */
 
115
        LogicIterator::LogicIterator ( const yy::location& loc, Iterator_t arg0, Iterator_t arg1, LogicType lt)
 
116
        :
 
117
                Batcher<LogicIterator> ( loc), iterLeft(arg0), iterRight(arg1), logicType(lt) {}
 
118
        LogicIterator::~LogicIterator(){}
 
119
                        
 
120
        Item_t 
 
121
        LogicIterator::nextImpl(IteratorTreeStateBlock& stateBlock)
 
122
        {
 
123
                bool bRes;
 
124
                
 
125
                STACK_INIT();
 
126
                switch(this->logicType)
 
127
                {
 
128
                case AND:
 
129
                        bRes = FnBooleanIterator::effectiveBooleanValue(this->loc, stateBlock, this->iterLeft)->getBooleanValue() 
 
130
                                                        && FnBooleanIterator::effectiveBooleanValue(this->loc, stateBlock, this->iterRight)->getBooleanValue();
 
131
                        break;
 
132
                case OR:
 
133
                        bRes = FnBooleanIterator::effectiveBooleanValue(this->loc, stateBlock, this->iterLeft)->getBooleanValue() 
 
134
                                                        || FnBooleanIterator::effectiveBooleanValue(this->loc, stateBlock, this->iterRight)->getBooleanValue();;
 
135
                        break;
 
136
                }
 
137
                STACK_PUSH(zorba::getZorbaForCurrentThread()->getItemFactory()->createBoolean(bRes));
 
138
                STACK_END();
 
139
        }
 
140
        
 
141
        void 
 
142
        LogicIterator::resetImpl(IteratorTreeStateBlock& stateBlock)
 
143
        {
 
144
                this->resetChild( this->iterLeft, stateBlock );
 
145
                this->resetChild( this->iterRight, stateBlock );
 
146
        }
 
147
        
 
148
        void 
 
149
        LogicIterator::releaseResourcesImpl(IteratorTreeStateBlock& stateBlock)
 
150
        {
 
151
                this->releaseChildResources( this->iterLeft, stateBlock );
 
152
                this->releaseChildResources( this->iterRight, stateBlock );
 
153
        }
 
154
        /* end class LogicIterator */
 
155
 
 
156
        /* begin class ComparisonIterator */
 
157
        CompareIterator::CompareIterator ( const yy::location& loc, Iterator_t arg0, Iterator_t arg1, CompareType argCompType )
 
158
        :
 
159
                Batcher<CompareIterator> ( loc ), compareType(argCompType) 
 
160
        {
 
161
                this->genericCast = new GenericCast();
 
162
                this->iter0 = new FnDataIterator ( loc, arg0 );
 
163
                this->iter1 = new FnDataIterator ( loc, arg1 );
 
164
        }
 
165
        
 
166
        CompareIterator::~CompareIterator()
 
167
        {
 
168
                delete this->genericCast;
 
169
        }
 
170
        
 
171
        Item_t
 
172
        CompareIterator::nextImpl(IteratorTreeStateBlock& stateBlock)
 
173
        {
 
174
                Item_t item0;
 
175
                Item_t item1;
 
176
                TypeCode type0;
 
177
                TypeCode type1;
 
178
                TypeCode resultType;
 
179
                TempSeq_t temp0;
 
180
                TempSeq_t temp1;
 
181
                int32_t i0;
 
182
                int32_t i1;
 
183
                bool found;
 
184
                bool empty;
 
185
                int32_t compareResult;
 
186
 
 
187
                STACK_INIT();
 
188
 
 
189
                if (this->isGeneralComparison())
 
190
                {
 
191
                        // TODO Optimizations for >, >=, < and <=
 
192
                        temp0 = zorba::getZorbaForCurrentThread()->getStore()->createTempSeq(this->iter0);
 
193
                        temp1 = zorba::getZorbaForCurrentThread()->getStore()->createTempSeq(this->iter1);
 
194
                        i0 = 1;
 
195
                        found = false;
 
196
                        while (!found && temp0->containsItem(i0))
 
197
                        {
 
198
                                i1 = 1;
 
199
                                while (!found && temp1->containsItem(i1))
 
200
                                {
 
201
                                        if (CompareIterator::generalComparison(temp0->getItem( i0 ), temp1->getItem( i1 )))
 
202
                                                found = true;
 
203
                                        i1++;
 
204
                                }
 
205
                                i0++;
 
206
                        }
 
207
 
 
208
                        STACK_PUSH( zorba::getZorbaForCurrentThread()->getItemFactory()->createBoolean( found ) );
 
209
                } /* if general comparison */
 
210
                else if (this->isValueComparison())
 
211
                {
 
212
                        if (( (item0 = this->consumeNext(this->iter0, stateBlock)) != NULL ) 
 
213
                                                && ((item1 = this->consumeNext(this->iter1, stateBlock))!=NULL))
 
214
                        {
 
215
                                STACK_PUSH( zorba::getZorbaForCurrentThread()->getItemFactory()->createBoolean( CompareIterator::valueComparison(item0, item1) ) );
 
216
                                if (this->consumeNext(this->iter0, stateBlock) != NULL || this->consumeNext(this->iter1, stateBlock) != NULL)
 
217
                                {
 
218
                                        ZorbaErrorAlerts::error_alert (
 
219
                                                error_messages::FOCH0004_Collation_does_not_support_collation_units,
 
220
                                                error_messages::RUNTIME_ERROR,
 
221
                                                &loc,
 
222
                                                false,
 
223
                                                "Value comparions must not be made with sequences with length greater 1!"
 
224
                                        );
 
225
                                }
 
226
                        }
 
227
                } /* if value comparison */
 
228
                else if (this->isNodeComparison())
 
229
                {
 
230
                        ZorbaErrorAlerts::error_alert (
 
231
                                error_messages::XQP0015_SYSTEM_NOT_YET_IMPLEMENTED,
 
232
                                error_messages::RUNTIME_ERROR,
 
233
                                &loc,
 
234
                                false,
 
235
                                "Node comparison is not yet implemented!"
 
236
                        );
 
237
                } /* if node comparison */
 
238
                
 
239
                STACK_END();
 
240
        }
 
241
 
 
242
        void
 
243
        CompareIterator::resetImpl(IteratorTreeStateBlock& stateBlock)
 
244
        {
 
245
                this->resetChild ( this->iter0, stateBlock );
 
246
                this->resetChild ( this->iter1, stateBlock );
 
247
        }
 
248
 
 
249
        void
 
250
        CompareIterator::releaseResourcesImpl(IteratorTreeStateBlock& stateBlock)
 
251
        {
 
252
                this->releaseChildResources ( this->iter0, stateBlock );
 
253
                this->releaseChildResources ( this->iter1, stateBlock );
 
254
        }
 
255
        
 
256
        bool 
 
257
        CompareIterator::isValueComparison()
 
258
        {
 
259
                bool retVal = false;
 
260
                switch(this->compareType)
 
261
                {
 
262
                case VALUE_EQUAL:
 
263
                case VALUE_NOT_EQUAL:
 
264
                case VALUE_LESS:
 
265
                case VALUE_LESS_EQUAL:
 
266
                case VALUE_GREATER:
 
267
                case VALUE_GREATER_EQUAL:
 
268
                        retVal = true;
 
269
                        break;
 
270
                default:
 
271
                        retVal = false;
 
272
                        break;
 
273
                }
 
274
                return retVal;
 
275
        }
 
276
        
 
277
        bool 
 
278
        CompareIterator::isGeneralComparison()
 
279
        {
 
280
                bool retVal = false;
 
281
                switch(this->compareType)
 
282
                {
 
283
                case GENERAL_EQUAL:
 
284
                case GENERAL_NOT_EQUAL:
 
285
                case GENERAL_LESS:
 
286
                case GENERAL_LESS_EQUAL:
 
287
                case GENERAL_GREATER:
 
288
                case GENERAL_GREATER_EQUAL:
 
289
                        retVal = true;
 
290
                        break;
 
291
                default:
 
292
                        retVal = false;
 
293
                        break;
 
294
                }
 
295
                return retVal;
 
296
        }
 
297
        
 
298
        bool
 
299
        CompareIterator::isNodeComparison()
 
300
        {
 
301
                bool retVal = false;
 
302
                switch(this->compareType)
 
303
                {
 
304
                case NODE_EQUAL:
 
305
                case NODE_NOT_EQUAL:
 
306
                        retVal = true;
 
307
                        break;
 
308
                default:
 
309
                        retVal = false;
 
310
                        break;
 
311
                }
 
312
                return retVal;
 
313
        }
 
314
        
 
315
        bool
 
316
        CompareIterator::generalComparison(Item_t item0, Item_t item1)
 
317
        {
 
318
                
 
319
                if (sequence_type::derives_from(item0->getType(), xs_untypedAtomicValue))
 
320
                {
 
321
                        if (sequence_type::isNumeric(item1->getType()))
 
322
                        {
 
323
                                this->genericCast->setTarget(xs_double);
 
324
                                item0 = this->genericCast->cast(item0);
 
325
                        }
 
326
                        else if (sequence_type::derives_from(item1->getType(), xs_untypedAtomicValue)
 
327
                                                                || sequence_type::derives_from(item1->getType(), xs_string))
 
328
                        {
 
329
                                this->genericCast->setTarget(xs_string);
 
330
                                item0 = this->genericCast->cast(item0);
 
331
                        }
 
332
                        else
 
333
                        {
 
334
                                this->genericCast->setTarget(item1->getType());
 
335
                                item0 = this->genericCast->cast(item0);
 
336
                        }
 
337
                }
 
338
                
 
339
                if (sequence_type::derives_from(item1->getType(), xs_untypedAtomicValue))
 
340
                {
 
341
                        if (sequence_type::isNumeric(item0->getType()))
 
342
                        {
 
343
                                this->genericCast->setTarget(xs_double);
 
344
                                item1 = this->genericCast->cast(item1);
 
345
                        }
 
346
                        else if (sequence_type::derives_from(item0->getType(), xs_untypedAtomicValue)
 
347
                                                                || sequence_type::derives_from(item0->getType(), xs_string))
 
348
                        {
 
349
                                this->genericCast->setTarget(xs_string);
 
350
                                item1 = this->genericCast->cast(item1);
 
351
                        }
 
352
                        else
 
353
                        {
 
354
                                this->genericCast->setTarget(item0->getType());
 
355
                                item1 = this->genericCast->cast(item1);
 
356
                        }
 
357
                }
 
358
                
 
359
                return CompareIterator::valueComparison(item0, item1);
 
360
        } /* end CompareIterator::generalComparison (...) */
 
361
 
 
362
        bool
 
363
        CompareIterator::valueComparison(Item_t item0, Item_t item1)
 
364
        {
 
365
                // all untyped Atomics to String
 
366
                if (sequence_type::derives_from(item0->getType(), xs_untypedAtomicValue))
 
367
                {
 
368
                        this->genericCast->setTarget(xs_string);
 
369
                        item0 = this->genericCast->cast(item0);
 
370
                }
 
371
                if  (sequence_type::derives_from(item1->getType(), xs_untypedAtomicValue))
 
372
                {
 
373
                        this->genericCast->setTarget(xs_string);
 
374
                        item1 = this->genericCast->cast(item1);
 
375
                }
 
376
                
 
377
                // TYPE PROMOTION
 
378
                // numeric promotion
 
379
                if (sequence_type::derives_from(item0->getType(), xs_float)) {
 
380
                        if (sequence_type::derives_from(item1->getType(), xs_decimal))
 
381
                        {
 
382
                                this->genericCast->setTarget(xs_float);
 
383
                                item1 = this->genericCast->cast(item1);
 
384
                        }
 
385
                }
 
386
                else if (sequence_type::derives_from(item0->getType(), xs_double))
 
387
                {
 
388
                        if (sequence_type::derives_from(item1->getType(), xs_decimal))
 
389
                        {
 
390
                                this->genericCast->setTarget(xs_double);
 
391
                                item1 = this->genericCast->cast(item1);
 
392
                        }
 
393
                        else if (sequence_type::derives_from(item0->getType(), xs_float))
 
394
                        {
 
395
                                this->genericCast->setTarget(xs_double);
 
396
                                item1 = this->genericCast->cast(item1);
 
397
                        }
 
398
                }
 
399
                
 
400
                if (sequence_type::derives_from(item1->getType(), xs_float)) {
 
401
                        if (sequence_type::derives_from(item0->getType(), xs_decimal))
 
402
                        {
 
403
                                this->genericCast->setTarget(xs_float);
 
404
                                item0 = this->genericCast->cast(item0);
 
405
                        }
 
406
                }
 
407
                else if (sequence_type::derives_from(item1->getType(), xs_double))
 
408
                {
 
409
                        if (sequence_type::derives_from(item0->getType(), xs_decimal))
 
410
                        {
 
411
                                this->genericCast->setTarget(xs_double);
 
412
                                item0 = this->genericCast->cast(item0);
 
413
                        }
 
414
                        else if (sequence_type::derives_from(item0->getType(), xs_float))
 
415
                        {
 
416
                                this->genericCast->setTarget(xs_double);
 
417
                                item0 = this->genericCast->cast(item0);
 
418
                        }
 
419
                }
 
420
                // uri promotion
 
421
                if (sequence_type::derives_from(item0->getType(), xs_string)
 
422
                                && sequence_type::derives_from(item1->getType(), xs_anyURI)) 
 
423
                {
 
424
                        this->genericCast->setTarget(xs_string);
 
425
                        item1 = this->genericCast->cast(item1);
 
426
                }
 
427
                if (sequence_type::derives_from(item1->getType(), xs_string)
 
428
                                && sequence_type::derives_from(item0->getType(), xs_anyURI)) 
 
429
                {
 
430
                        this->genericCast->setTarget(xs_string);
 
431
                        item0 = this->genericCast->cast(item0);
 
432
                }
 
433
 
 
434
                // computation of result
 
435
                int32_t compValue = -2;
 
436
                switch(this->compareType)
 
437
                {
 
438
                        case VALUE_EQUAL:
 
439
                        case GENERAL_EQUAL:
 
440
                        case VALUE_NOT_EQUAL:
 
441
                        case GENERAL_NOT_EQUAL:
 
442
                                compValue = CompareIterator::equal(item0, item1);
 
443
                                break;
 
444
                        case VALUE_GREATER:
 
445
                        case GENERAL_GREATER:
 
446
                        case VALUE_GREATER_EQUAL:
 
447
                        case GENERAL_GREATER_EQUAL:
 
448
                        case VALUE_LESS:
 
449
                        case GENERAL_LESS:
 
450
                        case VALUE_LESS_EQUAL:
 
451
                        case GENERAL_LESS_EQUAL:
 
452
                                compValue = CompareIterator::compare(item0, item1);
 
453
                        default:
 
454
                                break;
 
455
                }
 
456
                
 
457
                if (compValue > -2)
 
458
                        switch(this->compareType)
 
459
                        {
 
460
                                case VALUE_EQUAL:
 
461
                                case GENERAL_EQUAL:
 
462
                                        return compValue == 0;
 
463
                                        break;
 
464
                                case VALUE_NOT_EQUAL:
 
465
                                case GENERAL_NOT_EQUAL:
 
466
                                        return compValue != 0;
 
467
                                        break;
 
468
                                case VALUE_GREATER:
 
469
                                case GENERAL_GREATER:
 
470
                                        return compValue > 0;
 
471
                                        break;
 
472
                                case VALUE_GREATER_EQUAL:
 
473
                                case GENERAL_GREATER_EQUAL:
 
474
                                        return compValue >= 0;
 
475
                                        break;
 
476
                                case VALUE_LESS:
 
477
                                case GENERAL_LESS:
 
478
                                        return compValue < 0;
 
479
                                        break;
 
480
                                case VALUE_LESS_EQUAL:
 
481
                                case GENERAL_LESS_EQUAL:
 
482
                                        return compValue <= 0;
 
483
                                        break;
 
484
                                default:
 
485
                                        break;
 
486
                        }
 
487
                        
 
488
                ZorbaErrorAlerts::error_alert (
 
489
                        error_messages::FOCH0004_Collation_does_not_support_collation_units,
 
490
                        error_messages::RUNTIME_ERROR,
 
491
                        &loc,
 
492
                        false,
 
493
                        "Compare of declared collation operator and operators is not possible!"
 
494
                );
 
495
                return false;
 
496
        } /* end CompareIterator::valueComparison (...) */
 
497
        
 
498
        int32_t
 
499
        CompareIterator::equal(const Item_t& item0, const Item_t& item1)
 
500
        {
 
501
                // tries first normal compare
 
502
                int32_t compareRes = CompareIterator::compare(item0, item1);
 
503
                if (compareRes == 0)
 
504
                        return 0;
 
505
                else if (compareRes == -1 || compareRes == 1)
 
506
                        return 1;
 
507
                        
 
508
                TypeCode type0 = item0->getType();
 
509
                TypeCode type1 = item1->getType();
 
510
                bool equal;
 
511
                if (sequence_type::derives_from(type0, xs_boolean) && sequence_type::derives_from(type1, xs_boolean))
 
512
                                equal = item0->equals(item1);
 
513
                // TODO the rest
 
514
                else
 
515
                        return -2;
 
516
                
 
517
                if (equal)
 
518
                        return 0;
 
519
                else
 
520
                        return 1;
 
521
        }
 
522
        
 
523
        int32_t 
 
524
        CompareIterator::compare(const Item_t& item0, const Item_t& item1)
 
525
        {
 
526
                TypeCode type0 = item0->getType();
 
527
                TypeCode type1 = item1->getType();
 
528
                int32_t ret = -2;
 
529
                if (sequence_type::derives_from(type0, xs_float) && sequence_type::derives_from(type1, xs_float))
 
530
                        if ( item0->getFloatValue() < item1->getFloatValue())
 
531
                                ret = -1;
 
532
                        else if ( item0->getFloatValue() == item1->getFloatValue())
 
533
                                ret = 0;
 
534
                        else
 
535
                                ret = 1;
 
536
                else if (sequence_type::derives_from(type0, xs_double) && sequence_type::derives_from(type1, xs_double))
 
537
                        if ( item0->getDoubleValue() < item1->getDoubleValue())
 
538
                                ret = -1;
 
539
                        else if ( item0->getDoubleValue() == item1->getDoubleValue())
 
540
                                ret = 0;
 
541
                        else
 
542
                                ret = 1;
 
543
                else if (sequence_type::derives_from(type0, xs_decimal) && sequence_type::derives_from(type1, xs_decimal))
 
544
                        if ( item0->getDecimalValue() < item1->getDecimalValue())
 
545
                                ret = -1;
 
546
                        else if ( item0->getDecimalValue() == item1->getDecimalValue())
 
547
                                ret = 0;
 
548
                        else
 
549
                                ret = 1;
 
550
                else if (sequence_type::derives_from(type0, xs_string) && sequence_type::derives_from(type1, xs_string))
 
551
                        if ( item0->getStringValue() < item1->getStringValue())
 
552
                                ret = -1;
 
553
                        else if ( item0->getStringValue() == item1->getStringValue())
 
554
                                ret = 0;
 
555
                        else
 
556
                                ret = 1;
 
557
                // TODO comparisons for all types
 
558
 
 
559
                return ret;
 
560
        }
 
561
        /* end class ComparisonIterator */
 
562
 
 
563
}