KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > quadcap > sql > MergeCursor


1 package com.quadcap.sql;
2
3 /* Copyright 1999 - 2003 Quadcap Software. All rights reserved.
4  *
5  * This software is distributed under the Quadcap Free Software License.
6  * This software may be used or modified for any purpose, personal or
7  * commercial. Open Source redistributions are permitted. Commercial
8  * redistribution of larger works derived from, or works which bundle
9  * this software requires a "Commercial Redistribution License"; see
10  * http://www.quadcap.com/purchase.
11  *
12  * Redistributions qualify as "Open Source" under one of the following terms:
13  *
14  * Redistributions are made at no charge beyond the reasonable cost of
15  * materials and delivery.
16  *
17  * Redistributions are accompanied by a copy of the Source Code or by an
18  * irrevocable offer to provide a copy of the Source Code for up to three
19  * years at the cost of materials and delivery. Such redistributions
20  * must allow further use, modification, and redistribution of the Source
21  * Code under substantially the same terms as this license.
22  *
23  * Redistributions of source code must retain the copyright notices as they
24  * appear in each source code file, these license terms, and the
25  * disclaimer/limitation of liability set forth as paragraph 6 below.
26  *
27  * Redistributions in binary form must reproduce this Copyright Notice,
28  * these license terms, and the disclaimer/limitation of liability set
29  * forth as paragraph 6 below, in the documentation and/or other materials
30  * provided with the distribution.
31  *
32  * The Software is provided on an "AS IS" basis. No warranty is
33  * provided that the Software is free of defects, or fit for a
34  * particular purpose.
35  *
36  * Limitation of Liability. Quadcap Software shall not be liable
37  * for any damages suffered by the Licensee or any third party resulting
38  * from use of the Software.
39  */

40
41 import java.io.ByteArrayInputStream JavaDoc;
42 import java.io.Externalizable JavaDoc;
43 import java.io.IOException JavaDoc;
44 import java.io.ObjectInput JavaDoc;
45 import java.io.ObjectOutput JavaDoc;
46
47 import java.util.Vector JavaDoc;
48
49 import java.sql.SQLException JavaDoc;
50
51 import com.quadcap.sql.io.ObjectInputStream;
52 import com.quadcap.sql.io.ObjectOutputStream;
53
54 import com.quadcap.sql.file.ByteUtil;
55
56 import com.quadcap.sql.index.BCursor;
57 import com.quadcap.sql.index.Btree;
58
59 import com.quadcap.sql.types.Op;
60 import com.quadcap.sql.types.Value;
61
62 import com.quadcap.util.Debug;
63 import com.quadcap.util.Util;
64
65 /**
66  * Cursor implementing the SQL <b>UNION</b> or <b>INTERSECTION</b> operations.
67  * This cursor shares some functionality with the GroupByCursor class,
68  * and factorization should be investigated.
69  *
70  * @author Stan Bailes
71  */

72 public class MergeCursor extends CursorImpl {
73     int op;
74     boolean all;
75     TempTableMerge tempTable;
76     LazyRow row = null;
77     BCursor bc = null;
78     int duplicateCount = 0;
79
80     public MergeCursor(Session session, int op, boolean all,
81                TempTableMerge tempTable)
82     throws SQLException JavaDoc
83     {
84     super(session, null, null);
85     this.op = op;
86     this.all = all;
87     this.tempTable = tempTable;
88     }
89
90     public Row getRow() throws SQLException JavaDoc {
91     return row;
92     }
93
94     public void checkCursor() throws IOException JavaDoc {
95         if (bc == null) {
96             bc = tempTable.getCursor();
97         }
98     }
99
100     public long getRowId() {
101         byte[] val = bc.getValBuf();
102         return val[0] == 1 ? 0 : ByteUtil.getLong(val, 1);
103     }
104
105     public void resolveColumns() throws SQLException JavaDoc {
106     super.resolveColumns();
107     row = new LazyRow(getColumnCount());
108     beforeFirst();
109     }
110
111     public String JavaDoc getName() { return ""; }
112
113     public long size() throws SQLException JavaDoc {
114         try {
115             checkCursor();
116             return bc.size();
117         } catch (IOException JavaDoc e) {
118             throw DbException.wrapThrowable(e);
119         }
120     }
121     
122     public void afterLast() throws SQLException JavaDoc {
123         throw new SQLException JavaDoc("afterLast() not supported for this cursor type");
124     }
125
126     public boolean isWritable(int col) { return false; }
127
128     public boolean next() throws SQLException JavaDoc {
129     try {
130             checkCursor();
131         switch (op) {
132         case Op.UNION:
133         return all ? nextUnionAll() : nextUnion();
134         case Op.INTERSECT:
135         return nextIntersect();
136         case Op.EXCEPT:
137         return nextExcept();
138         default:
139         throw new SQLException JavaDoc("Bad merge op: " + op, "42000");
140         }
141     } catch (IOException JavaDoc e) {
142         throw DbException.wrapThrowable(e);
143     }
144     }
145
146     public void updateRow(Row row) throws SQLException JavaDoc {
147     throw new SQLException JavaDoc("GroupBy expressions aren't updateable",
148                    "42000");
149     }
150
151     public void deleteRow() throws SQLException JavaDoc {
152     throw new SQLException JavaDoc("GroupBy expressions aren't updateable",
153                    "42000");
154     }
155     
156     public void beforeFirst() throws SQLException JavaDoc {
157     try {
158             checkCursor();
159         bc.beforeFirst();
160     } catch (IOException JavaDoc e) {
161         throw DbException.wrapThrowable(e);
162     } finally {
163             duplicateCount = 0;
164         }
165     }
166
167     /**
168      * Separate from 'nextUnionAll' because we can avoid fetching the
169      * data for this case.
170      */

171     boolean nextUnion() throws SQLException JavaDoc, IOException JavaDoc {
172     if (!bc.next()) return false;
173     tempTable.getRow(bc.getValBuf(), row);
174     return true;
175     }
176
177     /**
178      * Fetch the data once when we fetch the counts, then return each
179      * row the required number of times
180      */

181     boolean nextUnionAll() throws SQLException JavaDoc, IOException JavaDoc {
182     if (duplicateCount-- <= 0) {
183         if (!bc.next()) return false;
184         tempTable.getRow(bc.getValBuf(), row);
185             byte[] data = bc.getValBuf();
186             int acnt = TempTableMerge.getCount(data, 0);
187             int bcnt = TempTableMerge.getCount(data, 1);
188         duplicateCount = acnt + bcnt - 1;
189         return true;
190     }
191     return true;
192     }
193
194     boolean nextIntersect() throws SQLException JavaDoc, IOException JavaDoc {
195     if (!all || duplicateCount-- <= 0) {
196         boolean found = false;
197         do {
198         if (!bc.next()) return false;
199         byte[] data = bc.getValBuf();
200         int acnt = TempTableMerge.getCount(data, 0);
201         int bcnt = TempTableMerge.getCount(data, 1);
202         duplicateCount =
203             all
204             ? Math.min(acnt, bcnt)
205             : (acnt > 0 && bcnt > 0) ? 1 : 0;
206         if (duplicateCount-- > 0) {
207             tempTable.getRow(data, row);
208             found = true;
209         }
210         } while (!found);
211         return found;
212     }
213     return true;
214     }
215     
216     boolean nextExcept() throws SQLException JavaDoc, IOException JavaDoc {
217     if (!all || duplicateCount-- <= 0) {
218         boolean found = false;
219         do {
220         if (!bc.next()) return false;
221         byte[] data = bc.getValBuf();
222         int acnt = TempTableMerge.getCount(data, 0);
223         int bcnt = TempTableMerge.getCount(data, 1);
224         duplicateCount =
225             all
226             ? (acnt - bcnt)
227             : (acnt > 0 && bcnt == 0) ? 1 : 0;
228         if (duplicateCount-- > 0) {
229             tempTable.getRow(data, row);
230             found = true;
231         }
232         } while (!found);
233         return found;
234     }
235     return true;
236     }
237     
238     /**
239      * On close, we release the resources.
240      */

241     public void close() throws SQLException JavaDoc {
242         try {
243             if (bc != null) bc.release();
244         } finally {
245             bc = null;
246             try {
247                 if (tempTable != null) tempTable.release();
248             } catch (IOException JavaDoc e2) {
249                 throw DbException.wrapThrowable(e2);
250             } finally {
251                 tempTable = null;
252             }
253         }
254     }
255 }
256
Popular Tags