KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hsqldb > Result


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 package org.hsqldb;
68
69 import java.io.DataInput JavaDoc;
70 import java.io.IOException JavaDoc;
71 import java.io.OutputStream JavaDoc;
72 import java.util.NoSuchElementException JavaDoc;
73
74 import org.hsqldb.lib.Iterator;
75 import org.hsqldb.rowio.RowInputBinary;
76 import org.hsqldb.rowio.RowOutputBinary;
77
78 // fredt@users 20020130 - patch 1.7.0 by fredt
79
// to ensure consistency of r.rTail r.iSize in all operations
80
// methods for set operations moved here from Select.java
81
// tony_lai@users 20020820 - patch 595073 - duplicated exception msg
82
// fredt@users 20030801 - patch 1.7.2 - separate metadata and polymophic serialisation
83
// boucherb@users 200307/8 - various, in support of fred's work over the same time period
84

85 /**
86  * The primary unit of comunication between Connection, Server and Session
87  * objects.
88  *
89  * An HSQLDB Result object encapsulates all requests (such as to alter or
90  * query session settings, to allocate and execute statements, etc.) and all
91  * responses (such as exception indications, update counts, result sets and
92  * result set metadata). It also implements the HSQL wire protocol for
93  * comunicating all such requests and responses across the network.
94  *
95  * Extensively rewritten and extended in successive versions of HSQLDB.
96  *
97  * @author Thomas Mueller (Hypersonic SQL Group)
98  * @version 1.8.0
99  * @since Hypersonic SQL
100  */

101 public class Result {
102
103     // record list
104
public Record rRoot;
105     private Record rTail;
106     private int size;
107
108     // transient - number of significant columns
109
private int significantColumns;
110
111     // type of result
112
public int mode;
113
114 // boolean isMulti;
115
// database ID
116
int databaseID;
117
118     // session ID
119
int sessionID;
120
121     // user / password or error strings
122
String JavaDoc mainString;
123     String JavaDoc subString;
124
125     // database name
126
String JavaDoc subSubString;
127
128     // the exception if this is an error
129
private Throwable JavaDoc exception;
130
131     // prepared statement id / error vendor code
132
int statementID;
133
134     // max rows (out) or update count (in)
135
int updateCount;
136     public ResultMetaData metaData;
137
138     /** A Result object's metadata */
139     public static class ResultMetaData {
140
141         // always resolved
142
public String JavaDoc[] colLabels;
143         public String JavaDoc[] tableNames;
144         public String JavaDoc[] colNames;
145         public boolean[] isLabelQuoted;
146         public int[] colTypes;
147         public int[] colSizes;
148         public int[] colScales;
149
150         // extra attrs, sometimes resolved
151
public String JavaDoc[] catalogNames;
152         public String JavaDoc[] schemaNames;
153         public int[] colNullable;
154         public boolean[] isIdentity;
155         public boolean[] isWritable;
156         public int[] paramMode;
157
158         // It's possible to do better than java.lang.Object
159
// for type OTHER if the expression generating the value
160
// is of type FUNCTION. This applies to result set columns
161
// whose value is the result of a SQL function call and
162
// especially to the arguments and return value of a CALL
163
public String JavaDoc[] classNames;
164         boolean isParameterDescription;
165
166         ResultMetaData() {}
167
168         ResultMetaData(int n) {
169             prepareData(n);
170         }
171
172         /**
173          * Method declaration
174          *
175          * @param columns
176          */

177         private void prepareData(int columns) {
178
179             colLabels = new String JavaDoc[columns];
180             tableNames = new String JavaDoc[columns];
181             colNames = new String JavaDoc[columns];
182             isLabelQuoted = new boolean[columns];
183             colTypes = new int[columns];
184             colSizes = new int[columns];
185             colScales = new int[columns];
186             catalogNames = new String JavaDoc[columns];
187             schemaNames = new String JavaDoc[columns];
188             colNullable = new int[columns];
189             isIdentity = new boolean[columns];
190             isWritable = new boolean[columns];
191             classNames = new String JavaDoc[columns];
192         }
193
194         public int[] getParameterTypes() {
195             return colTypes;
196         }
197
198         boolean isTableColumn(int i) {
199             return tableNames[i] != null && tableNames[i].length() > 0
200                    && colNames[i] != null && colNames[i].length() > 0;
201         }
202
203         private void decodeTableColumnAttrs(int in, int i) {
204
205             colNullable[i] = in & 0x0000000f;
206             isIdentity[i] = (in & 0x00000010) != 0;
207             isWritable[i] = (in & 0x00000020) != 0;
208         }
209
210         private void writeTableColumnAttrs(RowOutputBinary out,
211                                            int i)
212                                            throws IOException JavaDoc, HsqlException {
213
214             // HSQLDB also ignores precision and scale for all types except
215
// XXXCHAR, for which it may (or may not) perform some trimming/padding.
216
// All in all, it's currently meaningless (indeed misleading) to
217
// transmit and report the values, as the data typically will
218
// not be constrained accordingly.
219
// switch(colType[i]) {
220
// // As early as SQL 92, these are allowed to have a scale.
221
// // However, DatabaseCommandInterpreter.processCreateColumn
222
// // does not currently handle this correctly and will assign
223
// // a precision instead of a scale if TIME(s) or TIMESTAMP(s)
224
// // is specified
225
// case Types.TIME :
226
// case Types.TIMESTAMP :
227
// out.writeIntData(colScale[i]);
228
// break;
229
// case Types.DECIMAL :
230
// case Types.NUMERIC : {
231
// out.writeIntData(colScale[i]);
232
// } // fall through
233
// // Apparently, SQL 92 specifies that FLOAT can have
234
// // a declared precision, which is typically the number of
235
// // bits (not binary digits). In any case, this is somewhat
236
// // meaningless under HSQLDB/Java, in that we use java.lang.Double
237
// // to represent SQL FLOAT
238
// case Types.FLOAT :
239
// // It's legal to declare precision for these, although HSQLDB
240
// // currently does not use it to constrain values
241
// case Types.BINARY :
242
// case Types.VARBINARY :
243
// case Types.LONGVARBINARY :
244
// // possibly, but not universally acted upon (trimmming/padding)
245
// case Types.CHAR :
246
// case Types.VARCHAR :
247
// case Types.LONGVARCHAR : {
248
// out.writeIntData(colSize[i]);
249
// }
250
// }
251
out.writeIntData(encodeTableColumnAttrs(i));
252             out.writeString(catalogNames[i] == null ? ""
253                                                     : catalogNames[i]);
254             out.writeString(schemaNames[i] == null ? ""
255                                                    : schemaNames[i]);
256         }
257
258         private int encodeTableColumnAttrs(int i) {
259
260             int out = colNullable[i]; // always between 0x00 and 0x02
261

262             if (isIdentity[i]) {
263                 out |= 0x00000010;
264             }
265
266             if (isWritable[i]) {
267                 out |= 0x00000020;
268             }
269
270             return out;
271         }
272
273         private void readTableColumnAttrs(RowInputBinary in,
274                                           int i)
275                                           throws IOException JavaDoc, HsqlException {
276
277             decodeTableColumnAttrs(in.readIntData(), i);
278
279             catalogNames[i] = in.readString();
280             schemaNames[i] = in.readString();
281         }
282
283         ResultMetaData(RowInputBinary in,
284                        int mode) throws HsqlException, IOException JavaDoc {
285
286             int l = in.readIntData();
287
288             prepareData(l);
289
290             if (mode == ResultConstants.PARAM_META_DATA) {
291                 isParameterDescription = true;
292                 paramMode = new int[l];
293             }
294
295             for (int i = 0; i < l; i++) {
296                 colTypes[i] = in.readType();
297
298                 // fredt - 1.8.0 added
299
colSizes[i] = in.readIntData();
300                 colScales[i] = in.readIntData();
301                 colLabels[i] = in.readString();
302                 tableNames[i] = in.readString();
303                 colNames[i] = in.readString();
304                 classNames[i] = in.readString();
305
306                 if (isTableColumn(i)) {
307                     readTableColumnAttrs(in, i);
308                 }
309
310                 if (mode == ResultConstants.PARAM_META_DATA) {
311                     paramMode[i] = in.readIntData();
312                 }
313             }
314         }
315
316         void write(RowOutputBinary out,
317                    int colCount) throws HsqlException, IOException JavaDoc {
318
319             out.writeIntData(colCount);
320
321             for (int i = 0; i < colCount; i++) {
322                 out.writeType(colTypes[i]);
323
324                 // fredt - 1.8.0 added
325
out.writeIntData(colSizes[i]);
326                 out.writeIntData(colScales[i]);
327                 out.writeString(colLabels[i] == null ? ""
328                                                      : colLabels[i]);
329                 out.writeString(tableNames[i] == null ? ""
330                                                       : tableNames[i]);
331                 out.writeString(colNames[i] == null ? ""
332                                                     : colNames[i]);
333                 out.writeString(classNames[i] == null ? ""
334                                                       : classNames[i]);
335
336                 if (isTableColumn(i)) {
337                     writeTableColumnAttrs(out, i);
338                 }
339
340                 if (isParameterDescription) {
341                     out.writeIntData(paramMode[i]);
342                 }
343             }
344         }
345     }
346
347     /**
348      * General constructor
349      */

350     public Result(int type) {
351
352         mode = type;
353
354 /*
355         if (type == ResultConstants.MULTI) {
356             isMulti = true;
357         }
358 */

359         if (type == ResultConstants.DATA
360                 || type == ResultConstants.PARAM_META_DATA
361                 || type == ResultConstants.SQLEXECUTE
362                 || type == ResultConstants.SETSESSIONATTR) {
363             metaData = new ResultMetaData();
364         }
365     }
366
367     Result(ResultMetaData md) {
368
369         mode = ResultConstants.DATA;
370         significantColumns = md.colTypes.length;
371         metaData = md;
372     }
373
374 // fredt@users 20020221 - patch 513005 by sqlbob@users (RMP)
375

376     /**
377      * Constructor for errors
378      *
379      * @param error error message
380      * @param state sql state
381      * @param code vendor code
382      */

383     Result(String JavaDoc error, String JavaDoc state, int code) {
384
385         mode = ResultConstants.ERROR;
386         mainString = error;
387         subString = state;
388         statementID = code;
389         subSubString = "";
390     }
391
392     /**
393      * Only used with DATA and PARAM_META_DATA results
394      *
395      * @param columns
396      */

397     Result(int type, int columns) {
398
399         metaData = new ResultMetaData();
400
401         metaData.prepareData(columns);
402
403         if (type == ResultConstants.PARAM_META_DATA) {
404             metaData.isParameterDescription = true;
405             metaData.paramMode = new int[columns];
406         }
407
408         mode = type;
409         significantColumns = columns;
410     }
411
412     /**
413      * For BATCHEXECUTE and BATCHEXECDIRECT
414      */

415     public Result(int type, int[] types, int id) {
416
417         mode = type;
418         metaData = new ResultMetaData();
419         metaData.colTypes = types;
420         significantColumns = types.length;
421         statementID = id;
422     }
423
424     /**
425      * Constructor declaration
426      *
427      * @param in
428      * @exception HsqlException Description of the Exception
429      */

430     Result(RowInputBinary in) throws HsqlException {
431
432         try {
433             mode = in.readIntData();
434
435             if (mode == ResultConstants.MULTI) {
436                 readMultiResult(in);
437
438                 return;
439             }
440
441             databaseID = in.readIntData();
442             sessionID = in.readIntData();
443
444             switch (mode) {
445
446                 case ResultConstants.GETSESSIONATTR :
447                 case ResultConstants.SQLDISCONNECT :
448                 case ResultConstants.SQLSTARTTRAN :
449                 case ResultConstants.HSQLRESETSESSION :
450                     break;
451
452                 case ResultConstants.SQLPREPARE :
453                     setStatementType(in.readIntData());
454
455                     mainString = in.readString();
456                     break;
457
458                 case ResultConstants.PREPARE_ACK :
459                 case ResultConstants.SQLFREESTMT :
460                     statementID = in.readIntData();
461                     break;
462
463                 case ResultConstants.SQLEXECDIRECT :
464                     updateCount = in.readIntData();
465                     statementID = in.readIntData();
466                     mainString = in.readString();
467                     break;
468
469                 case ResultConstants.ERROR :
470                 case ResultConstants.SQLCONNECT :
471                     mainString = in.readString();
472                     subString = in.readString();
473                     subSubString = in.readString();
474                     statementID = in.readIntData();
475
476 // throw Trace.getError(string, code);
477
break;
478
479                 case ResultConstants.UPDATECOUNT :
480                     updateCount = in.readIntData();
481                     break;
482
483                 case ResultConstants.SQLENDTRAN : {
484                     int type = in.readIntData();
485
486                     setEndTranType(type); // endtran type
487

488                     switch (type) {
489
490                         case ResultConstants.SAVEPOINT_NAME_RELEASE :
491                         case ResultConstants.SAVEPOINT_NAME_ROLLBACK :
492                             mainString = in.readString(); // savepoint name
493
}
494
495                     break;
496                 }
497                 case ResultConstants.BATCHEXECUTE :
498                 case ResultConstants.BATCHEXECDIRECT :
499                 case ResultConstants.SQLEXECUTE :
500                 case ResultConstants.SETSESSIONATTR : {
501                     updateCount = in.readIntData();
502                     statementID = in.readIntData();
503
504                     int l = in.readIntData();
505
506                     metaData = new ResultMetaData(l);
507                     significantColumns = l;
508
509                     for (int i = 0; i < l; i++) {
510                         metaData.colTypes[i] = in.readType();
511                     }
512
513                     int count = in.readIntData();
514
515                     while (count-- > 0) {
516                         add(in.readData(metaData.colTypes));
517                     }
518
519                     break;
520                 }
521                 case ResultConstants.DATA :
522                 case ResultConstants.PARAM_META_DATA : {
523                     metaData = new ResultMetaData(in, mode);
524                     significantColumns = metaData.colLabels.length;
525
526                     int count = in.readIntData();
527
528                     while (count-- > 0) {
529                         add(in.readData(metaData.colTypes));
530                     }
531
532                     break;
533                 }
534                 case ResultConstants.SQLSETCONNECTATTR : {
535                     int type = in.readIntData(); // attr type
536

537                     setConnectionAttrType(type);
538
539                     switch (type) {
540
541                         case ResultConstants.SQL_ATTR_SAVEPOINT_NAME :
542                             mainString = in.readString(); // savepoint name
543

544                         // case ResultConstants.SQL_ATTR_AUTO_IPD :
545
// - always true
546
// default: throw - case never happens
547
}
548
549                     break;
550                 }
551                 default :
552                     throw new HsqlException(
553                         Trace.getMessage(
554                             Trace.Result_Result, true, new Object JavaDoc[]{
555                                 new Integer JavaDoc(mode) }), null, 0);
556             }
557         } catch (IOException JavaDoc e) {
558             throw Trace.error(Trace.TRANSFER_CORRUPTED);
559         }
560     }
561
562     static Result newSingleColumnResult(String JavaDoc colName, int colType) {
563
564         Result result = new Result(ResultConstants.DATA, 1);
565
566         result.metaData.colNames[0] = colName;
567         result.metaData.colLabels[0] = colName;
568         result.metaData.tableNames[0] = "";
569         result.metaData.colTypes[0] = colType;
570
571         return result;
572     }
573
574     static Result newPrepareResponse(int csid, Result rsmd, Result pmd) {
575
576         Result out;
577         Result pack;
578
579         out = new Result(ResultConstants.MULTI);
580
581 // out.isMulti = true;
582
pack = new Result(ResultConstants.PREPARE_ACK);
583         pack.statementID = csid;
584
585         out.add(new Object JavaDoc[]{ pack });
586         out.add(new Object JavaDoc[]{ rsmd });
587         out.add(new Object JavaDoc[]{ pmd });
588
589         return out;
590     }
591
592     static Result newParameterDescriptionResult(int len) {
593
594         Result r = new Result(ResultConstants.PARAM_META_DATA, len);
595
596         r.metaData.isParameterDescription = true;
597         r.metaData.paramMode = new int[len];
598
599         return r;
600     }
601
602     public static Result newFreeStmtRequest(int statementID) {
603
604         Result r = new Result(ResultConstants.SQLFREESTMT);
605
606         r.statementID = statementID;
607
608         return r;
609     }
610
611     static Result newExecuteDirectRequest(String JavaDoc sql) {
612
613         Result out;
614
615         out = new Result(ResultConstants.SQLEXECDIRECT);
616
617         out.setMainString(sql);
618
619         return out;
620     }
621
622     public static Result newReleaseSavepointRequest(String JavaDoc name) {
623
624         Result out;
625
626         out = new Result(ResultConstants.SQLENDTRAN);
627
628         out.setMainString(name);
629         out.setEndTranType(ResultConstants.SAVEPOINT_NAME_RELEASE);
630
631         return out;
632     }
633
634     public static Result newRollbackToSavepointRequest(String JavaDoc name) {
635
636         Result out;
637
638         out = new Result(ResultConstants.SQLENDTRAN);
639
640         out.setMainString(name);
641         out.setEndTranType(ResultConstants.SAVEPOINT_NAME_ROLLBACK);
642
643         return out;
644     }
645
646     public static Result newSetSavepointRequest(String JavaDoc name) {
647
648         Result out;
649
650         out = new Result(ResultConstants.SQLSETCONNECTATTR);
651
652         out.setConnectionAttrType(ResultConstants.SQL_ATTR_SAVEPOINT_NAME);
653         out.setMainString(name);
654
655         return out;
656     }
657
658     /**
659      * Method declaration
660      *
661      * @return
662      */

663     public int getSize() {
664         return size;
665     }
666
667     /**
668      * Method declaration
669      *
670      * @param columns
671      */

672     void setColumnCount(int columns) {
673         significantColumns = columns;
674     }
675
676     /**
677      * Method declaration
678      *
679      * @return
680      */

681     public int getColumnCount() {
682         return significantColumns;
683     }
684
685     /**
686      * Append Result argument to this.
687      *
688      * @param a
689      */

690     void append(Result a) {
691
692         if (a.rRoot == null) {
693             return;
694         }
695
696         if (rRoot == null) {
697             rRoot = a.rRoot;
698         } else {
699             rTail.next = a.rRoot;
700         }
701
702         rTail = a.rTail;
703         size += a.size;
704     }
705
706     void addAll(Result r) {
707
708         if (r == null) {
709             return;
710         }
711
712         Record from = r.rRoot;
713
714         while (from != null) {
715             add(from.data);
716
717             from = from.next;
718         }
719     }
720
721     public void clear() {
722
723         rRoot = null;
724         rTail = null;
725         size = 0;
726     }
727
728     public boolean isEmpty() {
729         return rRoot == null;
730     }
731
732     /**
733      * Method declaration
734      *
735      * @param a
736      */

737     void setRows(Result a) {
738
739         if (a == null) {
740             rRoot = null;
741             rTail = null;
742             size = 0;
743         } else {
744             rRoot = a.rRoot;
745             rTail = a.rTail;
746             size = a.size;
747         }
748     }
749
750     /**
751      * Method declaration
752      *
753      * @param d
754      */

755     public void add(Object JavaDoc[] d) {
756
757         Record r = new Record();
758
759         r.data = d;
760
761         if (rRoot == null) {
762             rRoot = r;
763         } else {
764             rTail.next = r;
765         }
766
767         rTail = r;
768
769         size++;
770     }
771
772     /**
773      * Method declaration
774      *
775      * @param limitstart number of records to discard at the head
776      * @param limitcount number of records to keep, all the rest if 0
777      */

778
779 // fredt@users 20020130 - patch 1.7.0 by fredt
780
// rewritten and moved from Select.java
781
void trimResult(int limitstart, int limitcount) {
782
783         Record n = rRoot;
784
785         if (n == null) {
786             return;
787         }
788
789         if (limitstart >= size) {
790             size = 0;
791             rRoot = rTail = null;
792
793             return;
794         }
795
796         size -= limitstart;
797
798         for (int i = 0; i < limitstart; i++) {
799             n = n.next;
800
801             if (n == null) {
802
803                 // if iSize is consistent this block will never be reached
804
size = 0;
805                 rRoot = rTail = n;
806
807                 return;
808             }
809         }
810
811         rRoot = n;
812
813         if (limitcount == 0 || limitcount >= size) {
814             return;
815         }
816
817         for (int i = 1; i < limitcount; i++) {
818             n = n.next;
819
820             if (n == null) {
821
822                 // if iSize is consistent this block will never be reached
823
return;
824             }
825         }
826
827         size = limitcount;
828         n.next = null;
829         rTail = n;
830     }
831
832     /**
833      * Removes duplicate rows on the basis of comparing the singificant
834      * columns of the rows in the result.
835      *
836      * @throws HsqlException
837      */

838     void removeDuplicates(Session session) throws HsqlException {
839         removeDuplicates(session, significantColumns);
840     }
841
842     /**
843      * Removes duplicate rows on the basis of comparing the first columnCount
844      * columns of rows in the result.
845      *
846      * @throws HsqlException
847      */

848
849 // fredt@users 20020130 - patch 1.7.0 by fredt
850
// to ensure consistency of r.rTail r.iSize in all set operations
851
void removeDuplicates(Session session,
852                           int columnCount) throws HsqlException {
853
854         if (rRoot == null) {
855             return;
856         }
857
858         int[] order = new int[columnCount];
859         int[] way = new int[columnCount];
860
861         for (int i = 0; i < columnCount; i++) {
862             order[i] = i;
863             way[i] = 1;
864         }
865
866         sortResult(session, order, way);
867
868         Record n = rRoot;
869
870         for (;;) {
871             Record next = n.next;
872
873             if (next == null) {
874                 break;
875             }
876
877             if (compareRecord(session, n.data, next.data, columnCount) == 0) {
878                 n.next = next.next;
879
880                 size--;
881             } else {
882                 n = next;
883             }
884         }
885
886         rTail = n;
887     }
888
889     /**
890      * Removes duplicates then removes the contents of the second result
891      * from this one base on first columnCount of the rows in each result.
892      *
893      * @param minus
894      * @throws HsqlException
895      */

896     void removeSecond(Session session, Result minus,
897                       int columnCount) throws HsqlException {
898
899         removeDuplicates(session, columnCount);
900         minus.removeDuplicates(session, columnCount);
901
902         Record n = rRoot;
903         Record last = rRoot;
904         boolean rootr = true; // checking rootrecord
905
Record n2 = minus.rRoot;
906         int i = 0;
907
908         while (n != null && n2 != null) {
909             i = compareRecord(session, n.data, n2.data, columnCount);
910
911             if (i == 0) {
912                 if (rootr) {
913                     rRoot = last = n.next;
914                 } else {
915                     last.next = n.next;
916                 }
917
918                 n = n.next;
919
920                 size--;
921             } else if (i > 0) { // r > minus
922
n2 = n2.next;
923             } else { // r < minus
924
last = n;
925                 rootr = false;
926                 n = n.next;
927             }
928         }
929
930         for (; n != null; ) {
931             last = n;
932             n = n.next;
933         }
934
935         rTail = last;
936     }
937
938     /**
939      * Removes all duplicate rows then removes all rows that are not shared
940      * between this and the other result, based on comparing the first
941      * columnCount columns of each result.
942      *
943      * @param r2
944      * @throws HsqlException
945      */

946     void removeDifferent(Session session, Result r2,
947                          int columnCount) throws HsqlException {
948
949         removeDuplicates(session, columnCount);
950         r2.removeDuplicates(session, columnCount);
951
952         Record n = rRoot;
953         Record last = rRoot;
954         boolean rootr = true; // checking rootrecord
955
Record n2 = r2.rRoot;
956         int i = 0;
957
958         size = 0;
959
960         while (n != null && n2 != null) {
961             i = compareRecord(session, n.data, n2.data, columnCount);
962
963