1 package com.quadcap.sql; 2 3 40 41 import java.io.ByteArrayOutputStream ; 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.BlockFile; 55 56 import com.quadcap.sql.types.Op; 57 import com.quadcap.sql.types.Type; 58 import com.quadcap.sql.types.Value; 59 60 import com.quadcap.util.Debug; 61 import com.quadcap.util.Util; 62 63 69 public class MergeExpression extends TableExpression 70 implements Externalizable 71 { 72 int op; 73 boolean all; 74 boolean corr; 75 TableExpression a; 76 TableExpression b; 77 Vector columns; 78 TempTableMerge tempTable; 79 MergeCursor mcursor = null; 80 int[] amap = null; 81 int[] bmap = null; 82 Type[] typeMap = null; 83 84 public MergeExpression() {} 85 86 public MergeExpression(int op, boolean all, TableExpression a, 87 TableExpression b, Vector columns, 88 boolean corr) { 89 this.op = op; 90 this.all = all; 91 this.a = a; 92 this.b = b; 93 this.columns = columns; 94 this.corr = corr; 95 } 96 97 public int rank() { return 2; } 98 99 public boolean isUpdatable() { return false; } 100 101 public void getBaseTables(Vector v) { 102 a.getBaseTables(v); 103 b.getBaseTables(v); 104 } 105 106 public void setWhere(Expression where) { 107 this.where = where; 108 a.setWhere(where); 109 b.setWhere(where); 110 } 111 112 public Cursor getCursor(Session session, Cursor c) throws SQLException { 113 try { 114 Cursor ca = a.getCursor(session, c); 115 Cursor cb = b.getCursor(session, c); 116 117 try { 118 checkCorresponding(ca, cb); 119 120 Key compare = new Key(amap.length); 121 122 tempTable = new TempTableMerge(session, compare); 123 tempTable.addRows(session, ca, 0, amap); 124 tempTable.addRows(session, cb, 1, bmap); 125 126 mcursor = new MergeCursor(session, op, all, tempTable); 127 128 if (!corr) { 129 for (int i = 1; i <= ca.getColumnCount(); i++) { 130 Column col = ca.getColumn(i); 131 mcursor.addColumn(new Column(col.getName(), col)); 132 } 133 } else { 134 for (int i = 0; i < amap.length; i++) { 135 Column col = ca.getColumn(amap[i]); 136 mcursor.addColumn(new Column(col.getName(), col)); 137 } 138 } 139 mcursor.resolveColumns(); 140 } finally { 141 ca.close(); 142 cb.close(); 143 } 144 } catch (IOException e) { 145 throw DbException.wrapThrowable(e); 146 } 147 return mcursor; 148 } 149 150 void checkCorresponding(Cursor ca, Cursor cb) throws SQLException { 151 if (!corr) { 152 if (ca.getColumnCount() != cb.getColumnCount()) { 153 throw new SQLException (Op.toString(op) + " merge " + 154 "operation, tables must have the " + 155 "same number of columns", "42000"); 156 } 157 amap = new int[ca.getColumnCount()]; 158 bmap = new int[amap.length]; 159 for (int i = 0; i < amap.length; i++) { 160 amap[i] = bmap[i] = i+1; 161 } 162 } else if (columns == null) { 163 int cnt = 0; 165 for (int i = 1; i <= ca.getColumnCount(); i++) { 166 Column cola = ca.getColumn(i); 167 Column colb = cb.getColumn(cola.getShortName()); 168 if (colb != null) { 169 cnt++; 170 } 171 } 172 if (cnt == 0) { 173 throw new SQLException (Op.toString(op) + " CORRESPONDING, " + 174 "no common columns found", "42000"); 175 } 176 amap = new int[cnt]; 177 bmap = new int[cnt]; 178 int p = 0; 179 for (int i = 1; i <= ca.getColumnCount(); i++) { 180 Column cola = ca.getColumn(i); 181 Column colb = cb.getColumn(cola.getShortName()); 182 if (colb != null) { 183 amap[p] = cola.getColumn(); 184 bmap[p] = colb.getColumn(); 185 p++; 186 } 187 } 188 } else { 189 amap = new int[columns.size()]; 190 bmap = new int[amap.length]; 191 192 for (int i = 0; i < columns.size(); i++) { 193 String name = (String )columns.elementAt(i); 194 Column cola = ca.getColumn(name); 195 if (cola == null) { 196 throw new SQLException ("Not found: " + name, "42000"); 197 } 198 amap[i] = cola.getColumn(); 199 200 Column colb = cb.getColumn(name); 201 if (colb == null) { 202 throw new SQLException ("Not found: " + name, "42000"); 203 } 204 bmap[i] = colb.getColumn(); 205 } 206 } 207 } 208 209 public void invert() { 210 throw new RuntimeException ( 211 "invert not implemented for MergeExpression"); 212 } 213 214 public void readExternal(ObjectInput in) 215 throws IOException , ClassNotFoundException 216 { 217 this.op = in.read(); 218 this.all = in.read() == 1; 219 this.a = (TableExpression)in.readObject(); 220 this.b = (TableExpression)in.readObject(); 221 this.columns = (Vector )in.readObject(); 222 this.corr = in.read() == 1; 223 } 224 225 public void writeExternal(ObjectOutput out) throws IOException { 226 out.write(op); 227 out.write(all ? 1 : 0); 228 out.writeObject(a); 229 out.writeObject(b); 230 out.writeObject(columns); 231 out.write(corr ? 1 : 0); 232 } 233 234 public void visitSubExpressions(ExpressionVisitor ev) { 235 ev.visit(a); 236 ev.visit(b); 237 } 238 239 public String toString() { 240 StringBuffer sb = new StringBuffer (a.toString()); 241 sb.append(' '); 242 sb.append(Op.toString(op)); 243 if (all) sb.append(" ALL"); 244 if (corr) { 245 sb.append(" CORRESPONDING"); 246 if (columns != null) { 247 sb.append(" BY ("); 248 for (int i = 0; i < columns.size(); i++) { 249 if (i > 0) sb.append(','); 250 sb.append(columns.get(i).toString()); 251 } 252 sb.append(")"); 253 } 254 } 255 sb.append(' '); 256 sb.append(b.toString()); 257 return sb.toString(); 258 } 259 260 public String name() { 262 StringBuffer sb = new StringBuffer ('('); 263 sb.append(a.name()); 264 sb.append(' '); 265 sb.append(Op.toString(op)); 266 sb.append(' '); 267 sb.append(b.name()); 268 sb.append(')'); 269 return sb.toString(); 270 } 271 } 273 | Popular Tags |