| 1 package com.quadcap.sql; 2 3 40 41 import java.io.ByteArrayInputStream ; 42 import java.io.Externalizable ; 43 import java.io.IOException ; 44 import java.io.ObjectInput ; 45 import java.io.ObjectOutput ; 46 47 import java.util.Vector ; 48 49 import java.sql.SQLException ; 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 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  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 { 91 return row; 92 } 93 94 public void checkCursor() throws IOException { 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 { 106 super.resolveColumns(); 107 row = new LazyRow(getColumnCount()); 108 beforeFirst(); 109 } 110 111 public String getName() { return ""; } 112 113 public long size() throws SQLException { 114 try { 115 checkCursor(); 116 return bc.size(); 117 } catch (IOException e) { 118 throw DbException.wrapThrowable(e); 119 } 120 } 121 122 public void afterLast() throws SQLException { 123 throw new SQLException ("afterLast() not supported for this cursor type"); 124 } 125 126 public boolean isWritable(int col) { return false; } 127 128 public boolean next() throws SQLException { 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 ("Bad merge op: " + op, "42000"); 140 } 141 } catch (IOException e) { 142 throw DbException.wrapThrowable(e); 143 } 144 } 145 146 public void updateRow(Row row) throws SQLException { 147 throw new SQLException ("GroupBy expressions aren't updateable", 148 "42000"); 149 } 150 151 public void deleteRow() throws SQLException { 152 throw new SQLException ("GroupBy expressions aren't updateable", 153 "42000"); 154 } 155 156 public void beforeFirst() throws SQLException { 157 try { 158 checkCursor(); 159 bc.beforeFirst(); 160 } catch (IOException e) { 161 throw DbException.wrapThrowable(e); 162 } finally { 163 duplicateCount = 0; 164 } 165 } 166 167 171 boolean nextUnion() throws SQLException , IOException { 172 if (!bc.next()) return false; 173 tempTable.getRow(bc.getValBuf(), row); 174 return true; 175 } 176 177 181 boolean nextUnionAll() throws SQLException , IOException { 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 , IOException { 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 , IOException { 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 241 public void close() throws SQLException { 242 try { 243 if (bc != null) bc.release(); 244 } finally { 245 bc = null; 246 try { 247 if (tempTable != null) tempTable.release(); 248 } catch (IOException e2) { 249 throw DbException.wrapThrowable(e2); 250 } finally { 251 tempTable = null; 252 } 253 } 254 } 255 } 256 | Popular Tags |