Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/hsqldb/Result.java


1   /* Copyrights and Licenses
2    *
3    * This product includes Hypersonic SQL.
4    * Originally developed by Thomas Mueller and the Hypersonic SQL Group. 
5    *
6    * Copyright (c) 1995-2000 by the Hypersonic SQL Group. All rights reserved. 
7    * Redistribution and use in source and binary forms, with or without modification, are permitted
8    * provided that the following conditions are met: 
9    *     -  Redistributions of source code must retain the above copyright notice, this list of conditions
10   *         and the following disclaimer. 
11   *     -  Redistributions in binary form must reproduce the above copyright notice, this list of
12   *         conditions and the following disclaimer in the documentation and/or other materials
13   *         provided with the distribution. 
14   *     -  All advertising materials mentioning features or use of this software must display the
15   *        following acknowledgment: "This product includes Hypersonic SQL." 
16   *     -  Products derived from this software may not be called "Hypersonic SQL" nor may
17   *        "Hypersonic SQL" appear in their names without prior written permission of the
18   *         Hypersonic SQL Group. 
19   *     -  Redistributions of any form whatsoever must retain the following acknowledgment: "This
20   *          product includes Hypersonic SQL." 
21   * This software is provided "as is" and any expressed or implied warranties, including, but
22   * not limited to, the implied warranties of merchantability and fitness for a particular purpose are
23   * disclaimed. In no event shall the Hypersonic SQL Group or its contributors be liable for any
24   * direct, indirect, incidental, special, exemplary, or consequential damages (including, but
25   * not limited to, procurement of substitute goods or services; loss of use, data, or profits;
26   * or business interruption). However caused any on any theory of liability, whether in contract,
27   * strict liability, or tort (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   * This software consists of voluntary contributions made by many individuals on behalf of the
30   * Hypersonic SQL Group.
31   *
32   *
33   * For work added by the HSQL Development Group:
34   *
35   * Copyright (c) 2001-2002, The HSQL Development Group
36   * All rights reserved.
37   *
38   * Redistribution and use in source and binary forms, with or without
39   * modification, are permitted provided that the following conditions are met:
40   *
41   * Redistributions of source code must retain the above copyright notice, this
42   * list of conditions and the following disclaimer, including earlier
43   * license statements (above) and comply with all above license conditions.
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, including earlier
48   * license statements (above) and comply with all above license conditions.
49   *
50   * Neither the name of the HSQL Development Group nor the names of its
51   * contributors may be used to endorse or promote products derived from this
52   * software without specific prior written permission.
53   *
54   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
55   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57   * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG, 
58   * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
59   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
60   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
61   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
62   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
63   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
64   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
65   */
66  
67  
68  package org.hsqldb;
69  
70  import java.io.IOException;
71  import java.sql.SQLException;
72  
73  // fredt@users 20020130 - patch 1.7.0 by fredt
74  // to ensure consistency of r.rTail r.iSize in all operations
75  // methods for set operations moved here from Select.java
76  // fredt@users 20020130 - patch 1.7.0 by fredt
77  // rewrite of LIMIT n m to apply to each select statement separately
78  // tony_lai@users 20020820 - patch 595073 by tlai@users - duplicated exception msg
79  
80  /**
81   *  Class declaration
82   *
83   * @version    1.7.0
84   */
85  class Result {
86  
87      private Record   rTail;
88      private int      iSize;
89      private int      iColumnCount;
90      static final int UPDATECOUNT = 0;
91      static final int ERROR       = 1;
92      static final int DATA        = 2;
93      int              iMode;
94      String           sError;
95      int              errorCode;
96      int              iUpdateCount;
97      Record           rRoot;
98      String           sLabel[];
99      String           sTable[];
100     String           sName[];
101     boolean          isLabelQuoted[];
102     int              colType[];
103     int              colSize[];
104     int              colScale[];
105 
106     /**
107      *  Constructor declaration
108      */
109     Result() {
110         iMode        = UPDATECOUNT;
111         iUpdateCount = 0;
112     }
113 
114 // fredt@users 20020221 - patch 513005 by sqlbob@users (RMP)
115 
116     /**
117      *  Constructor declaration
118      *
119      * @param  error
120      * @param  code   Description of the Parameter
121      */
122     Result(String error, int code) {
123 
124         iMode     = ERROR;
125         sError    = error;
126         errorCode = code;
127     }
128 
129     /**
130      *  Constructor declaration
131      *
132      * @param  columns
133      */
134     Result(int columns) {
135 
136         prepareData(columns);
137 
138         iColumnCount = columns;
139     }
140 
141     /**
142      *  Constructor declaration
143      *
144      * @param  b
145      * @exception  SQLException  Description of the Exception
146      */
147     Result(byte b[]) throws SQLException {
148 
149         try {
150             DatabaseRowInputInterface in = new BinaryServerRowInput(b);
151 
152             iMode = in.readIntData();
153 
154             if (iMode == ERROR) {
155 
156 // tony_lai@users 20020820 - patch 595073
157                 int code = in.readIntData();
158 
159                 throw Trace.getError(in.readString(), code);
160 
161 //                throw Trace.getError(in.readIntData(), in.readString());
162             } else if (iMode == UPDATECOUNT) {
163                 iUpdateCount = in.readIntData();
164             } else if (iMode == DATA) {
165                 int l = in.readIntData();
166 
167                 prepareData(l);
168 
169                 iColumnCount = l;
170 
171                 for (int i = 0; i < l; i++) {
172                     colType[i] = in.readType();
173                     sLabel[i]  = in.readString();
174                     sTable[i]  = in.readString();
175                     sName[i]   = in.readString();
176                 }
177 
178                 while (in.available() != 0) {
179                     add(in.readData(colType));
180                 }
181             }
182         } catch (IOException e) {
183             throw Trace.error(Trace.TRANSFER_CORRUPTED);
184         }
185     }
186 
187     /**
188      *  Method declaration
189      *
190      * @return
191      */
192     int getSize() {
193         return iSize;
194     }
195 
196     /**
197      *  Method declaration
198      *
199      * @param  columns
200      */
201     void setColumnCount(int columns) {
202         iColumnCount = columns;
203     }
204 
205     /**
206      *  Method declaration
207      *
208      * @return
209      */
210     int getColumnCount() {
211         return iColumnCount;
212     }
213 
214     /**
215      *  Method declaration
216      *
217      * @param  a
218      */
219     void append(Result a) {
220 
221         if (rRoot == null) {
222             rRoot = a.rRoot;
223         } else {
224             rTail.next = a.rRoot;
225         }
226 
227         rTail = a.rTail;
228         iSize += a.iSize;
229     }
230 
231     /**
232      *  Method declaration
233      *
234      * @param  a
235      */
236     void setRows(Result a) {
237 
238         rRoot = a.rRoot;
239         rTail = a.rTail;
240         iSize = a.iSize;
241     }
242 
243     /**
244      *  Method declaration
245      *
246      * @param  d
247      */
248     void add(Object d[]) {
249 
250         Record r = new Record();
251 
252         r.data = d;
253 
254         if (rRoot == null) {
255             rRoot = r;
256         } else {
257             rTail.next = r;
258         }
259 
260         rTail = r;
261 
262         iSize++;
263     }
264 
265     /**
266      *  Method declaration
267      *
268      * @param  limitstart  number of records to discard at the head
269      * @param  limitcount  number of records to keep, all the rest if 0
270      */
271 
272 // fredt@users 20020130 - patch 1.7.0 by fredt
273 // rewritten and moved from Select.java
274     void trimResult(int limitstart, int limitcount) {
275 
276         Record n = rRoot;
277 
278         if (n == null) {
279             return;
280         }
281 
282         if (limitstart >= iSize) {
283             iSize = 0;
284             rRoot = rTail = null;
285 
286             return;
287         }
288 
289         iSize -= limitstart;
290 
291         for (int i = 0; i < limitstart; i++) {
292             n = n.next;
293 
294             if (n == null) {
295 
296                 // if iSize is consistent this block will never be reached
297                 iSize = 0;
298                 rRoot = rTail = n;
299 
300                 return;
301             }
302         }
303 
304         rRoot = n;
305 
306         if (limitcount == 0 || limitcount >= iSize) {
307             return;
308         }
309 
310         for (int i = 1; i < limitcount; i++) {
311             n = n.next;
312 
313             if (n == null) {
314 
315                 // if iSize is consistent this block will never be reached
316                 return;
317             }
318         }
319 
320         n.next = null;
321         rTail  = n;
322     }
323 
324     /**
325      *  Method declaration
326      *
327      * @throws  SQLException
328      */
329 
330 // fredt@users 20020130 - patch 1.7.0 by fredt
331 // to ensure consistency of r.rTail r.iSize in all set operations
332     void removeDuplicates() throws SQLException {
333 
334         if (rRoot == null) {
335             return;
336         }
337 
338         int len     = getColumnCount();
339         int order[] = new int[len];
340         int way[]   = new int[len];
341 
342         for (int i = 0; i < len; i++) {
343             order[i] = i;
344             way[i]   = 1;
345         }
346 
347         sortResult(order, way);
348 
349         Record n = rRoot;
350 
351         for (;;) {
352             Record next = n.next;
353 
354             if (next == null) {
355                 break;
356             }
357 
358             if (compareRecord(n.data, next.data, len) == 0) {
359                 n.next = next.next;
360 
361                 iSize--;
362             } else {
363                 n = next;
364             }
365         }
366 
367         rTail = n;
368 
369         Trace.doAssert(rTail.next == null,
370                        "rTail not correct in Result.removeDuplicates iSise ="
371                        + iSize);
372     }
373 
374     /**
375      *  Method declaration
376      *
377      * @param  minus
378      * @throws  SQLException
379      */
380     void removeSecond(Result minus) throws SQLException {
381 
382         removeDuplicates();
383         minus.removeDuplicates();
384 
385         int     len   = getColumnCount();
386         Record  n     = rRoot;
387         Record  last  = rRoot;
388         boolean rootr = true;    // checking rootrecord
389         Record  n2    = minus.rRoot;
390         int     i     = 0;
391 
392         while (n != null && n2 != null) {
393             i = compareRecord(n.data, n2.data, len);
394 
395             if (i == 0) {
396                 if (rootr) {
397                     rRoot = last = n.next;
398                 } else {
399                     last.next = n.next;
400                 }
401 
402                 n = n.next;
403 
404                 iSize--;
405             } else if (i > 0) {    // r > minus
406                 n2 = n2.next;
407             } else {               // r < minus
408                 last  = n;
409                 rootr = false;
410                 n     = n.next;
411             }
412         }
413 
414         for (; n != null; ) {
415             last = n;
416             n    = n.next;
417         }
418 
419         rTail = last;
420 
421         Trace.doAssert(
422             (rRoot == null && rTail == null) || rTail.next == null,
423             "rTail not correct in Result.removeSecond iSise =" + iSize);
424     }
425 
426     /**
427      *  Method declaration
428      *
429      * @param  r2
430      * @throws  SQLException
431      */
432     void removeDifferent(Result r2) throws SQLException {
433 
434         removeDuplicates();
435         r2.removeDuplicates();
436 
437         int     len   = getColumnCount();
438         Record  n     = rRoot;
439         Record  last  = rRoot;
440         boolean rootr = true;    // checking rootrecord
441         Record  n2    = r2.rRoot;
442         int     i     = 0;
443 
444         iSize = 0;
445 
446         while (n != null && n2 != null) {
447             i = compareRecord(n.data, n2.data, len);
448 
449             if (i == 0) {             // same rows
450                 if (rootr) {
451                     rRoot = n;        // make this the first record
452                 } else {
453                     last.next = n;    // this is next record in resultset
454                 }
455 
456                 rootr = false;
457                 last  = n;            // this is last record in resultset
458                 n     = n.next;
459                 n2    = n2.next;
460 
461                 iSize++;
462             } else if (i > 0) {       // r > r2
463                 n2 = n2.next;
464             } else {                  // r < r2
465                 n = n.next;
466             }
467         }
468 
469         if (rootr) {             // if no lines in resultset
470             rRoot = null;        // then return null
471             last  = null;
472         } else {
473             last.next = null;    // else end resultset
474         }
475 
476         rTail = last;
477 
478         Trace.doAssert(
479             (rRoot == null && rTail == null) || rTail.next == null,
480             "rTail not correct in Result.removeDifference iSise =" + iSize);
481     }
482 
483     /**
484      *  Method declaration
485      *
486      * @param  order
487      * @param  way
488      * @throws  SQLException
489      */
490     void sortResult(int order[], int way[]) throws SQLException {
491 
492         if (rRoot == null || rRoot.next == null) {
493             return;
494         }
495 
496         Record source0, source1;
497         Record target[]     = new Record[2];
498         Record targetlast[] = new Record[2];
499         int    dest         = 0;
500         Record n            = rRoot;
501 
502         while (n != null) {
503             Record next = n.next;
504 
505             n.next       = target[dest];
506             target[dest] = n;
507             n            = next;
508             dest         ^= 1;
509         }
510 
511         for (int blocksize = 1; target[1] != null; blocksize <<= 1) {
512             source0   = target[0];
513             source1   = target[1];
514             target[0] = target[1] = targetlast[0] = targetlast[1] = null;
515 
516             for (dest = 0; source0 != null; dest ^= 1) {
517                 int n0 = blocksize,
518                     n1 = blocksize;
519 
520                 while (true) {
521                     if (n0 == 0 || source0 == null) {
522                         if (n1 == 0 || source1 == null) {
523                             break;
524                         }
525 
526                         n       = source1;
527                         source1 = source1.next;
528 
529                         n1--;
530                     } else if (n1 == 0 || source1 == null) {
531                         n       = source0;
532                         source0 = source0.next;
533 
534                         n0--;
535                     } else if (compareRecord(
536                             source0.data, source1.data, order, way) > 0) {
537                         n       = source1;
538                         source1 = source1.next;
539 
540                         n1--;
541                     } else {
542                         n       = source0;
543                         source0 = source0.next;
544 
545                         n0--;
546                     }
547 
548                     if (target[dest] == null) {
549                         target[dest] = n;
550                     } else {
551                         targetlast[dest].next = n;
552                     }
553 
554                     targetlast[dest] = n;
555                     n.next           = null;
556                 }
557             }
558         }
559 
560         rRoot = target[0];
561         rTail = targetlast[0];
562 
563         Trace.doAssert(rTail.next == null,
564                        "rTail not correct in Result.sortResult iSise ="
565                        + iSize);
566     }
567 
568     /**
569      *  Method declaration
570      *
571      * @param  a
572      * @param  b
573      * @param  order
574      * @param  way
575      * @return
576      * @throws  SQLException
577      */
578     private int compareRecord(Object a[], Object b[], int order[],
579                               int way[]) throws SQLException {
580 
581         int i = Column.compare(a[order[0]], b[order[0]], colType[order[0]]);
582 
583         if (i == 0) {
584             for (int j = 1; j < order.length; j++) {
585                 i = Column.compare(a[order[j]], b[order[j]],
586                                    colType[order[j]]);
587 
588                 if (i != 0) {
589                     return i * way[j];
590                 }
591             }
592         }
593 
594         return i * way[0];
595     }
596 
597     /**
598      *  Method declaration
599      *
600      * @param  a
601      * @param  b
602      * @param  len
603      * @return
604      * @throws  SQLException
605      */
606     private int compareRecord(Object a[], Object b[],
607                               int len) throws SQLException {
608 
609         for (int j = 0; j < len; j++) {
610             int i = Column.compare(a[j], b[j], colType[j]);
611 
612             if (i != 0) {
613                 return i;
614             }
615         }
616 
617         return 0;
618     }
619 
620 // fredt@users 20020221 - patch 513005 by sqlbob@users (RMP)
621 
622     /**
623      *  Method declaration
624      *
625      * @return
626      * @throws  SQLException
627      */
628     byte[] getBytes() throws SQLException {
629 
630         try {
631             DatabaseRowOutputInterface out = new BinaryServerRowOutput();
632 
633             out.writeIntData(iMode);
634 
635             if (iMode == UPDATECOUNT) {
636                 out.writeIntData(iUpdateCount);
637             } else if (iMode == ERROR) {
638                 out.writeIntData(errorCode);
639                 out.writeString(sError);
640             } else {
641                 int l = iColumnCount;
642 
643                 out.writeIntData(l);
644 
645                 Record n = rRoot;
646 
647                 for (int i = 0; i < l; i++) {
648                     out.writeType(colType[i]);
649                     out.writeString(sLabel[i]);
650                     out.writeString(sTable[i]);
651                     out.writeString(sName[i]);
652                 }
653 
654                 while (n != null) {
655                     out.writeData(l, colType, n.data);
656 
657                     n = n.next;
658                 }
659             }
660 
661             return out.toByteArray();
662         } catch (IOException e) {
663             throw Trace.error(Trace.TRANSFER_CORRUPTED);
664         }
665     }
666 
667     /**
668      *  Method declaration
669      *
670      * @param  columns
671      */
672     private void prepareData(int columns) {
673 
674         iMode         = DATA;
675         sLabel        = new String[columns];
676         sTable        = new String[columns];
677         sName         = new String[columns];
678         isLabelQuoted = new boolean[columns];
679         colType       = new int[columns];
680         colSize       = new int[columns];
681         colScale      = new int[columns];
682     }
683 }