~ubuntu-branches/ubuntu/maverick/hsqldb/maverick

« back to all changes in this revision

Viewing changes to src/org/hsqldb/Index.java

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2006-09-26 11:47:49 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060926114749-3jd0utm7w21x1iqt
Tags: 1.8.0.5-2ubuntu1
* Synchronise with Debian unstable; remaining changes:
  - build using java-gcj-compat.
* libhsqldb-java: Add gij as alternative dependency.
* Build a libhsqldb-java-gcj package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 1995-2000, The Hypersonic SQL Group.
2
 
 * All rights reserved.
3
 
 *
4
 
 * Redistribution and use in source and binary forms, with or without
5
 
 * modification, are permitted provided that the following conditions are met:
6
 
 *
7
 
 * Redistributions of source code must retain the above copyright notice, this
8
 
 * list of conditions and the following disclaimer.
9
 
 *
10
 
 * Redistributions in binary form must reproduce the above copyright notice,
11
 
 * this list of conditions and the following disclaimer in the documentation
12
 
 * and/or other materials provided with the distribution.
13
 
 *
14
 
 * Neither the name of the Hypersonic SQL Group nor the names of its
15
 
 * contributors may be used to endorse or promote products derived from this
16
 
 * software without specific prior written permission.
17
 
 *
18
 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 
 * ARE DISCLAIMED. IN NO EVENT SHALL THE HYPERSONIC SQL GROUP,
22
 
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23
 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24
 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25
 
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26
 
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28
 
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
 
 *
30
 
 * This software consists of voluntary contributions made by many individuals 
31
 
 * on behalf of the Hypersonic SQL Group.
32
 
 *
33
 
 *
34
 
 * For work added by the HSQL Development Group:
35
 
 *
36
 
 * Copyright (c) 2001-2005, The HSQL Development Group
37
 
 * All rights reserved.
38
 
 *
39
 
 * Redistribution and use in source and binary forms, with or without
40
 
 * modification, are permitted provided that the following conditions are met:
41
 
 *
42
 
 * Redistributions of source code must retain the above copyright notice, this
43
 
 * list of conditions and the following disclaimer.
44
 
 *
45
 
 * Redistributions in binary form must reproduce the above copyright notice,
46
 
 * this list of conditions and the following disclaimer in the documentation
47
 
 * and/or other materials provided with the distribution.
48
 
 *
49
 
 * Neither the name of the HSQL Development Group nor the names of its
50
 
 * contributors may be used to endorse or promote products derived from this
51
 
 * software without specific prior written permission.
52
 
 *
53
 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
54
 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55
 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56
 
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
57
 
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
58
 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
59
 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
60
 
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
61
 
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
62
 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
63
 
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64
 
 */
65
 
 
66
 
 
 
1
/* Copyright (c) 1995-2000, The Hypersonic SQL Group.
 
2
 * All rights reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions are met:
 
6
 *
 
7
 * Redistributions of source code must retain the above copyright notice, this
 
8
 * list of conditions and the following disclaimer.
 
9
 *
 
10
 * Redistributions in binary form must reproduce the above copyright notice,
 
11
 * this list of conditions and the following disclaimer in the documentation
 
12
 * and/or other materials provided with the distribution.
 
13
 *
 
14
 * Neither the name of the Hypersonic SQL Group nor the names of its
 
15
 * contributors may be used to endorse or promote products derived from this
 
16
 * software without specific prior written permission.
 
17
 *
 
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
19
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
21
 * ARE DISCLAIMED. IN NO EVENT SHALL THE HYPERSONIC SQL GROUP,
 
22
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
23
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
24
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
25
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 
26
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
28
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
29
 *
 
30
 * This software consists of voluntary contributions made by many individuals 
 
31
 * on behalf of the Hypersonic SQL Group.
 
32
 *
 
33
 *
 
34
 * For work added by the HSQL Development Group:
 
35
 *
 
36
 * Copyright (c) 2001-2005, The HSQL Development Group
 
37
 * All rights reserved.
 
38
 *
 
39
 * Redistribution and use in source and binary forms, with or without
 
40
 * modification, are permitted provided that the following conditions are met:
 
41
 *
 
42
 * Redistributions of source code must retain the above copyright notice, this
 
43
 * list of conditions and the following disclaimer.
 
44
 *
 
45
 * Redistributions in binary form must reproduce the above copyright notice,
 
46
 * this list of conditions and the following disclaimer in the documentation
 
47
 * and/or other materials provided with the distribution.
 
48
 *
 
49
 * Neither the name of the HSQL Development Group nor the names of its
 
50
 * contributors may be used to endorse or promote products derived from this
 
51
 * software without specific prior written permission.
 
52
 *
 
53
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
54
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
55
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
56
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 
57
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
58
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
59
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
60
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 
61
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
62
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
63
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
64
 */
 
65
 
 
66
 
67
67
package org.hsqldb;
68
68
 
69
69
import java.util.NoSuchElementException;
257
257
        }
258
258
    }
259
259
 
260
 
    Node getRoot(Session session) {
261
 
 
262
 
        if (isTemp) {
 
260
    int getRoot() {
 
261
        return (root == null) ? -1
 
262
                              : root.getKey();
 
263
    }
 
264
 
 
265
    private Node getRoot(Session session) {
 
266
 
 
267
        if (isTemp && session != null) {
263
268
            return session.getIndexRoot(indexName, onCommitPreserve);
264
269
        } else {
265
270
            return root;
289
294
                break;
290
295
            }
291
296
 
292
 
            compare = compareRowUnique(session, row, n.getRow());
 
297
            compare = compareRowForInsert(session, row, n.getRow());
293
298
 
294
299
            if (compare == 0) {
295
300
                throw Trace.error(Trace.VIOLATION_OF_UNIQUE_INDEX,
314
319
            int sign = isleft ? 1
315
320
                              : -1;
316
321
 
 
322
            x = x.getUpdatedNode();
 
323
 
317
324
            switch (x.getBalance() * sign) {
318
325
 
319
326
                case 1 :
332
339
                        replace(session, x, l);
333
340
                        set(x, isleft, child(l, !isleft));
334
341
                        set(l, !isleft, x);
 
342
 
 
343
                        x = x.getUpdatedNode();
 
344
 
335
345
                        x.setBalance(0);
 
346
 
 
347
                        l = l.getUpdatedNode();
 
348
 
336
349
                        l.setBalance(0);
337
350
                    } else {
338
351
                        Node r = child(l, !isleft);
339
352
 
340
353
                        replace(session, x, r);
341
 
                        set(l, !isleft, child(r, isleft));
 
354
                        set(l, !isleft, child(r.getUpdatedNode(), isleft));
342
355
                        set(r, isleft, l);
343
 
                        set(x, isleft, child(r, !isleft));
 
356
                        set(x, isleft, child(r.getUpdatedNode(), !isleft));
344
357
                        set(r, !isleft, x);
345
358
 
346
 
                        int rb = r.getBalance();
 
359
                        int rb = r.getUpdatedNode().getBalance();
347
360
 
348
 
                        x.setBalance((rb == -sign) ? sign
349
 
                                                   : 0);
350
 
                        l.setBalance((rb == sign) ? -sign
351
 
                                                  : 0);
352
 
                        r.setBalance(0);
 
361
                        x.getUpdatedNode().setBalance((rb == -sign) ? sign
 
362
                                                                    : 0);
 
363
                        l.getUpdatedNode().setBalance((rb == sign) ? -sign
 
364
                                                                   : 0);
 
365
                        r.getUpdatedNode().setBalance(0);
353
366
                    }
354
367
 
355
368
                    return;
356
369
            }
357
370
 
358
 
            if (x.equals(getRoot(session))) {
 
371
            x = x.getUpdatedNode();
 
372
 
 
373
            if (x.isRoot()) {
359
374
                return;
360
375
            }
361
376
 
410
425
            // swap d and x
411
426
            int b = x.getBalance();
412
427
 
 
428
            x = x.getUpdatedNode();
 
429
 
413
430
            x.setBalance(d.getBalance());
 
431
 
 
432
            d = d.getUpdatedNode();
 
433
 
414
434
            d.setBalance(b);
415
435
 
416
436
            // set x.parent
417
437
            Node xp = x.getParent();
418
438
            Node dp = d.getParent();
419
439
 
420
 
            if (d == getRoot(session)) {
 
440
            x = x.getUpdatedNode();
 
441
 
 
442
            if (d.isRoot()) {
421
443
                setRoot(session, x);
422
444
            }
423
445
 
424
446
            x.setParent(dp);
425
447
 
426
448
            if (dp != null) {
427
 
                if (dp.getRight().equals(d)) {
 
449
                dp = dp.getUpdatedNode();
 
450
 
 
451
                if (dp.isRight(d)) {
428
452
                    dp.setRight(x);
429
453
                } else {
430
454
                    dp.setLeft(x);
431
455
                }
432
456
            }
433
457
 
434
 
            // for in-memory tables we could use: d.rData=x.rData;
435
 
            // but not for cached tables
436
458
            // relink d.parent, x.left, x.right
437
 
            if (xp == d) {
 
459
            d = d.getUpdatedNode();
 
460
 
 
461
            if (d.equals(xp)) {
438
462
                d.setParent(x);
439
463
 
440
 
                if (d.getLeft().equals(x)) {
 
464
                if (d.isLeft(x)) {
 
465
                    x = x.getUpdatedNode();
 
466
 
441
467
                    x.setLeft(d);
442
 
                    x.setRight(d.getRight());
 
468
 
 
469
                    Node dr = d.getRight();
 
470
 
 
471
                    x = x.getUpdatedNode();
 
472
 
 
473
                    x.setRight(dr);
443
474
                } else {
444
475
                    x.setRight(d);
445
 
                    x.setLeft(d.getLeft());
 
476
 
 
477
                    Node dl = d.getLeft();
 
478
 
 
479
                    x = x.getUpdatedNode();
 
480
 
 
481
                    x.setLeft(dl);
446
482
                }
447
483
            } else {
448
484
                d.setParent(xp);
 
485
 
 
486
                xp = xp.getUpdatedNode();
 
487
 
449
488
                xp.setRight(d);
450
 
                x.setRight(d.getRight());
451
 
                x.setLeft(d.getLeft());
 
489
 
 
490
                Node dl = d.getLeft();
 
491
                Node dr = d.getRight();
 
492
 
 
493
                x = x.getUpdatedNode();
 
494
 
 
495
                x.setLeft(dl);
 
496
                x.setRight(dr);
452
497
            }
453
498
 
454
499
            x.getRight().setParent(x);
455
500
            x.getLeft().setParent(x);
456
501
 
457
502
            // set d.left, d.right
 
503
            d = d.getUpdatedNode();
 
504
 
458
505
            d.setLeft(n);
459
506
 
460
507
            if (n != null) {
 
508
                n = n.getUpdatedNode();
 
509
 
461
510
                n.setParent(d);
462
511
            }
463
512
 
 
513
            d = d.getUpdatedNode();
 
514
 
464
515
            d.setRight(null);
465
516
 
466
517
            x = d;
471
522
        replace(session, x, n);
472
523
 
473
524
        n = x.getParent();
 
525
        x = x.getUpdatedNode();
474
526
 
475
527
        x.delete();
476
528
 
480
532
            int sign = isleft ? 1
481
533
                              : -1;
482
534
 
 
535
            x = x.getUpdatedNode();
 
536
 
483
537
            switch (x.getBalance() * sign) {
484
538
 
485
539
                case -1 :
501
555
                        set(r, isleft, x);
502
556
 
503
557
                        if (b == 0) {
 
558
                            x = x.getUpdatedNode();
 
559
 
504
560
                            x.setBalance(sign);
 
561
 
 
562
                            r = r.getUpdatedNode();
 
563
 
505
564
                            r.setBalance(-sign);
506
565
 
507
566
                            return;
508
567
                        }
509
568
 
 
569
                        x = x.getUpdatedNode();
 
570
 
510
571
                        x.setBalance(0);
 
572
 
 
573
                        r = r.getUpdatedNode();
 
574
 
511
575
                        r.setBalance(0);
512
576
 
513
577
                        x = r;
516
580
 
517
581
                        replace(session, x, l);
518
582
 
 
583
                        l = l.getUpdatedNode();
519
584
                        b = l.getBalance();
520
585
 
521
586
                        set(r, isleft, child(l, !isleft));
522
587
                        set(l, !isleft, r);
523
588
                        set(x, !isleft, child(l, isleft));
524
589
                        set(l, isleft, x);
 
590
 
 
591
                        x = x.getUpdatedNode();
 
592
 
525
593
                        x.setBalance((b == sign) ? -sign
526
594
                                                 : 0);
 
595
 
 
596
                        r = r.getUpdatedNode();
 
597
 
527
598
                        r.setBalance((b == -sign) ? sign
528
599
                                                  : 0);
 
600
 
 
601
                        l = l.getUpdatedNode();
 
602
 
529
603
                        l.setBalance(0);
530
604
 
531
605
                        x = l;
542
616
 
543
617
        Node node = findNotNull(session, rowdata, rowColMap, true);
544
618
 
545
 
        return node == null ? emptyIterator
546
 
                            : new IndexRowIterator(session, this, node);
 
619
        return getIterator(session, node);
547
620
    }
548
621
 
549
622
    RowIterator findFirstRowForDelete(Session session, Object[] rowdata,
550
623
                                      int[] rowColMap) throws HsqlException {
551
624
 
552
 
        Node node = findNotNull(session, rowdata, rowColMap, true);
553
 
 
554
 
        if (node == null) {
555
 
            return emptyIterator;
556
 
        } else {
557
 
            RowIterator it = new IndexRowIterator(session, this, node);
558
 
 
559
 
            updatableIterators.link((IndexRowIterator) it);
560
 
 
561
 
            return it;
 
625
        Node node           = findNotNull(session, rowdata, rowColMap, true);
 
626
        IndexRowIterator it = getIterator(session, node);
 
627
 
 
628
        if (node != null) {
 
629
            updatableIterators.link(it);
562
630
        }
 
631
 
 
632
        return it;
563
633
    }
564
634
 
565
 
    public Row findRow(Session session, Row row) throws HsqlException {
 
635
    /**
 
636
     * Finds an existing row
 
637
     */
 
638
    Row findRow(Session session, Row row) throws HsqlException {
566
639
 
567
640
        Node node = search(session, row);
568
641
 
702
775
     * only. The rowdata has the same column mapping as this table.
703
776
     *
704
777
     * @param rowdata array containing table row data
705
 
     * @return matching node
 
778
     * @return iterator
706
779
     * @throws HsqlException
707
780
     */
708
781
    RowIterator findFirstRow(Session session,
731
804
            }
732
805
        }
733
806
 
734
 
        return found == null ? emptyIterator
735
 
                             : new IndexRowIterator(session, this, found);
 
807
        return getIterator(session, found);
736
808
    }
737
809
 
738
810
    /**
742
814
     * @param value value to match
743
815
     * @param compare comparison Expression type
744
816
     *
745
 
     * @return matching node
 
817
     * @return iterator
746
818
     *
747
819
     * @throws HsqlException
748
820
     */
826
898
            }
827
899
        }
828
900
 
829
 
        return x == null ? emptyIterator
830
 
                         : new IndexRowIterator(session, this, x);
 
901
        return getIterator(session, x);
831
902
    }
832
903
 
833
904
    /**
834
905
     * Finds the first node where the data is not null.
835
906
     *
836
 
     * @return matching node
 
907
     * @return iterator
837
908
     *
838
909
     * @throws HsqlException
839
910
     */
874
945
            }
875
946
        }
876
947
 
877
 
        return x == null ? emptyIterator
878
 
                         : new IndexRowIterator(session, this, x);
 
948
        return getIterator(session, x);
879
949
    }
880
950
 
881
951
    /**
899
969
            depth++;
900
970
        }
901
971
 
902
 
        return x == null ? emptyIterator
903
 
                         : new IndexRowIterator(session, this, x);
 
972
        return getIterator(session, x);
904
973
    }
905
974
 
906
975
    /**
992
1061
    private void replace(Session session, Node x,
993
1062
                         Node n) throws HsqlException {
994
1063
 
995
 
        if (x.equals(getRoot(session))) {
 
1064
        if (x.isRoot()) {
 
1065
            if (n != null) {
 
1066
                n = n.getUpdatedNode();
 
1067
 
 
1068
                n.setParent(null);
 
1069
            }
 
1070
 
996
1071
            setRoot(session, n);
997
 
 
998
 
            if (n != null) {
999
 
                n.setParent(null);
1000
 
            }
1001
1072
        } else {
1002
1073
            set(x.getParent(), x.isFromLeft(), n);
1003
1074
        }
1014
1085
     */
1015
1086
    private void set(Node x, boolean isleft, Node n) throws HsqlException {
1016
1087
 
 
1088
        x = x.getUpdatedNode();
 
1089
 
1017
1090
        if (isleft) {
1018
1091
            x.setLeft(n);
1019
1092
        } else {
1021
1094
        }
1022
1095
 
1023
1096
        if (n != null) {
 
1097
            n = n.getUpdatedNode();
 
1098
 
1024
1099
            n.setParent(x);
1025
1100
        }
1026
1101
    }
1034
1109
     *
1035
1110
     * @throws HsqlException
1036
1111
     */
1037
 
    Node search(Session session, Row row) throws HsqlException {
 
1112
    private Node search(Session session, Row row) throws HsqlException {
1038
1113
 
1039
1114
        Object[] d = row.getData();
1040
1115
        Node     x = getRoot(session);
1041
1116
 
1042
1117
        while (x != null) {
1043
 
            int c = compareRowUnique(session, row, x.getRow());
 
1118
            int c = compareRowForInsert(session, row, x.getRow());
1044
1119
 
1045
1120
            if (c == 0) {
1046
1121
                return x;
1058
1133
     * Compares two table rows based on the columns of this index. The rowColMap
1059
1134
     * parameter specifies which columns of the other table are to be compared
1060
1135
     * with the colIndex columns of this index. The rowColMap can cover all
1061
 
     * or only some columns of this index. The invisible column is never
1062
 
     * compared
 
1136
     * or only some columns of this index.
1063
1137
     *
1064
1138
     * @param a row from another table
1065
1139
     * @param rowColMap column indexes in the other table
1129
1203
     *
1130
1204
     * @throws HsqlException
1131
1205
     */
1132
 
    private int compareRowUnique(Session session, Row left,
1133
 
                                 Row right) throws HsqlException {
 
1206
    private int compareRowForInsert(Session session, Row newRow,
 
1207
                                    Row existingRow) throws HsqlException {
1134
1208
 
1135
 
        Object[] a       = left.getData();
1136
 
        Object[] b       = right.getData();
 
1209
        Object[] a       = newRow.getData();
 
1210
        Object[] b       = existingRow.getData();
1137
1211
        int      j       = 0;
1138
1212
        boolean  hasNull = false;
1139
1213
 
1166
1240
        }
1167
1241
 
1168
1242
        if (useRowId) {
1169
 
            int difference = left.getPos() - right.getPos();
 
1243
            int difference = newRow.getPos() - existingRow.getPos();
1170
1244
 
1171
1245
            if (difference < 0) {
1172
1246
                difference = -1;
1211
1285
        }
1212
1286
    }
1213
1287
 
 
1288
    private IndexRowIterator getIterator(Session session, Node x) {
 
1289
 
 
1290
        if (x == null) {
 
1291
            return emptyIterator;
 
1292
        } else {
 
1293
            IndexRowIterator it = new IndexRowIterator(session, this, x);
 
1294
 
 
1295
            return it;
 
1296
        }
 
1297
    }
 
1298
 
1214
1299
    static class IndexRowIterator implements RowIterator {
1215
1300
 
1216
1301
        Session                    session;
1247
1332
 
1248
1333
                    return row;
1249
1334
                } catch (Exception e) {
1250
 
                    throw new NoSuchElementException();
 
1335
                    throw new NoSuchElementException(e.getMessage());
1251
1336
                }
1252
1337
            } else {
1253
1338
                return null;
1254
1339
            }
1255
1340
        }
1256
1341
 
 
1342
        void updateForDelete(Node node) {
 
1343
 
 
1344
            try {
 
1345
                if (node.equals(nextnode)) {
 
1346
                    nextnode = index.next(node);
 
1347
                }
 
1348
            } catch (Exception e) {}
 
1349
        }
 
1350
 
1257
1351
        void link(IndexRowIterator other) {
1258
1352
 
1259
1353
            other.next = next;
 
1354
            other.last = this;
1260
1355
            next.last  = other;
1261
 
            other.last = this;
1262
1356
            next       = other;
1263
1357
        }
1264
1358
 
1272
1366
                next.last = last;
1273
1367
            }
1274
1368
        }
1275
 
 
1276
 
        void updateForDelete(Node node) {
1277
 
 
1278
 
            try {
1279
 
                if (node.equals(nextnode)) {
1280
 
                    nextnode = index.next(node);
1281
 
                }
1282
 
            } catch (Exception e) {}
1283
 
        }
1284
1369
    }
1285
1370
}